2019.10.20 星期日
今天整个就不想学啦,主要是codeforces打不动了,卡在div3上不去,真的头大了今天,我不该暂停训练的,可我有什么办法呢?
上上周的北美资格赛的I题,就是我连WA了20多发的那道题,今天居然写出来,原因让我很无语,就是爆int了,当时想了半天没想到这点,今天在休闲debug的时候意外发现自己增加常数可以多过一两个case,然后索性换了long long, 结果一发入魂?我今天在图书馆直接骂出来了,有了这道题我们该是第一啊!!!!之前怀疑过自己的算法,怀疑过出题人,就是没怀疑过爆int,饿,当时比赛的时候认为两个floyd矩阵已经挤占了较大空间,然后就没有往longlong上想了,结果给我来了这一出,真是防不胜防!!!!难受也没用,当时要是想到这点就绝杀了,可惜啊,可惜,哎,明年不会比今年差的,codeforces打上去再说!!
下面出题解
题目: ICPC北美预选赛I题Slow Leak(传送门)
大多数人没法科学上网,我就借助地理优势给搬过来了,大意是车轮胎破了,然后骑车从1到n,m条路,每次骑车不能超过maxDist这个距离,轮胎的气可以在中间的q个维修站补足。
很好,当时比赛的想法就是dijkstra做深搜,然后每到一个点就开始减去可以骑车的距离,如果车在中途没气了(dist <= 0), 那么就剪枝进行下一条路的搜索。这样做的确可以,不过之后想到了一个更好的办法,那就是二维数组连边,然后跑一遍floyd多源最短路,最后只把加油站的点和起始点连起来,做dijkstra求最短路从1到n就行了。可惜了,没能及时找出爆int这个问题,大家看看吧。
下面放ac题解,我是用dijkstra做的,虽然这道题数据量很小(500)而且给足了时间,但是我觉得两遍floyd还是会挤占大量的时空内存,所以还是跑了一遍dijkstra。记得INF要开大,常用的0x3f3f3f3f是不行的
AC代码:
#include <bits/stdc++.h>
using namespace std;
#define limit 3000 + 5//防止溢出
#define INF 0x3f3f3f3f3f
#define inf 1<<20
#define lowbit(i) i&(-i)//一步两步
#define EPS 1e-6
#define ff(a) printf("%d\n",a );
#define MOD 1e9 + 7
typedef long long ll;
void read(int &x){
char ch = getchar();x = 0;
for (; ch < '0' || ch > '9'; ch = getchar());
for (; ch >='0' && ch <= '9'; ch = getchar()) x = x * 10 + ch - '0';
}//快读
int n , m , sta, k;
int vis[limit];
ll first[limit][limit];
struct edge{
int to;
ll weight;
edge(int tt = 0 , ll w = 0): to(tt), weight(w){}
bool operator<(const edge &rhs)const{
return weight > rhs.weight;
}
};
vector<vector<edge> >v;
int visited[limit];
ll dijkstra(){
edge u(1,0);
priority_queue<edge>q;
q.push(u);
int flag = 0;
for(int i = 0 ; i <= n ; ++i){
visited[i] = 0;
}
while(q.size()){
u = q.top();
q.pop();
if(visited[u.to])continue;
visited[u.to] = 1;
if(u.to == n){
flag = 1;
break;
}
for(int i = 0 ; i < v[u.to].size() ; ++i){
edge tmp = v[u.to][i];
if(visited[tmp.to])continue;
tmp.weight += u.weight;
q.push(tmp);
}
}
return flag ? u.weight : INF;
}
int main(){
//freopen("C:\\Users\\administrator01\\CLionProjects\\untitled14\\data.txt", "rt" , stdin);
scanf("%d%d%d%d" , &n , &m , &sta, &k);
for(int i = 1; i <= n ; ++i){
vis[i] = 0;
for(int j = 1 ; j <= n ; ++j){
if(i == j){
first[i][j] = 0;
}else{
first[i][j] = INF;
}
}
}
memset(vis, 0 , sizeof(vis));
for(int i = 0 ; i < sta; ++i){
int station;
scanf("%d" , &station);
vis[station] = 1;
}
for(int i = 0 ; i < m ;++i){
ll from , to , weight;
scanf("%lld%lld%lld" , &from, &to, &weight);
ll orig = first[from][to];
ll orig2 = first[to][from];
weight = min(orig, weight);
weight = min(orig2 , weight);
first[from][to] = first[to][from] = weight;
}
vis[1] = 1;
vis[n] = 1;
for(int k = 1; k <= n ; ++k){
for(int i = 1 ; i <= n ; ++i){
for(int j = 1 ; j <= n ; ++j){
first[i][j] = min(first[i][j], first[i][k] + first[k][j]);
}
}
}
v.resize(n + 1);
for(int i = 1 ; i <= n ; ++i){
for(int j = 1; j <= n ; ++j){
if(vis[i] && vis[j] && first[i][j] <= k && i != j){
v[i].push_back(edge(j, first[i][j]));
//v[j].push_back(edge(i, first[i][j]));
}
}
}
ll ans = dijkstra();
if(ans == INF){
printf("stuck");
}else{
printf("%lld", ans);
}
return 0;
};