问题描述
约翰在外地销售牛奶。这个地方有T个城市,编号为1到T。这些城市间有R条公路和P条 航线。公路都是可以双向通行的,第i条公路连接城市Ai和Bi,过路费为Ci。而航线都是单程 的,第i条航线从城市Xi出发,目的地是城市Yi,机票费为Di,由于航空公司竞争激烈,Di竟 可能是个负数!此外,由于反恐需要,政府在规划交通的时候曾保证,如果Xi到Yi有一条航 线,就不可能从Yi通过其他公路或航线返回Xi。
约翰拥有世界上公认的最给力的奶牛,所有城市的居民都渴望他的牛奶。约翰已决定将 配送中心设在S城,他想知道将牛奶从S城送到各个城镇的最少费用分别是多少。
输入格式
第一行:四个用空格分开的整数:T,R,P,S,1 ≤ S ≤ T ≤ 25000,1 ≤ P, R ≤ 50000 第二行到R + 1行:每行有三个用空格分开的整数,表示一条公路:Ai,Bi和Ci, 1 ≤ Ai,Bi ≤ T,0 ≤ Ci ≤ 10000
第R + 2行到R + P + 1行:每行有三个用空格分开的整数,表示一条航线:Xi,Yi和Di, 1 ≤ Xi, Yi ≤ T,−10000 ≤ Di ≤ 10000
输出格式
第一行到第T行:第K行有一个整数,表示从S到K的最小开销,如果根本到不了K,输出 “NO PATH”
样例输入
6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
样例输出
NO PATH
NO PATH
5
0
-95
-100
提示
从4 开始,走公路到可以3,从3坐飞机 可以到 5,从 4坐飞机可以到6,但不可能到 1 或2
题解
乍一看,最短路,随手打了个spfa就交了,然而这题是卡spfa的。。。
想到dijkstra堆优化好像是比spfa被卡的时候快的,懒得手打堆,用了STL的优先队列打了dijkstra,顺利过了样例和第二个数据,然而交上去T掉的点比spfa还多Σ(⊙▽⊙”a (dijkstra优先队列优化的常数比spfa大?)
于是只好老老实实手打堆。好不容易打好了,样例也过了,第二个数据死活过不了(ಥ﹏ಥ)。
突然想到dijkstra好像处理不了负权边。。。
难怪手打堆过不了。。。可是为什么优先队列没有wa?!
最后还是回到spfa,用了双端队列优化,再加上读入优化和输出优化,于是就过了。
所谓双端队列优化就是,假设节点v要入队,当前队首元素为u,如果dis[v]<dis[u]就把v插在对头,否则插在队尾。只要在入队的时候稍微改一下就好了。
1 #include <cstdio> 2 const int maxn=25000; 3 struct node{ 4 int u,nex; 5 int w; 6 }g[150005]; 7 int n,m,R,P,s,num,fir[25005]; 8 int q[25005],h,t; 9 int dis[25005]; 10 bool vis[25005]; 11 int read() 12 { 13 int f=1,s=0; 14 char ch; 15 ch=getchar(); 16 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 17 if (ch=='-') f=-1,ch=getchar(); 18 while (ch>='0' && ch<='9') 19 s=s*10+ch-'0',ch=getchar(); 20 return s*f; 21 } 22 void write(int x) 23 { 24 if (x<0) putchar('-'),x=-x; 25 if (x>9) write(x/10); 26 putchar(x%10+'0'); 27 return; 28 } 29 void add(int x,int y,int z) 30 { 31 g[++num].u=y; g[num].w=z; g[num].nex=fir[x]; fir[x]=num; 32 return; 33 } 34 void spfa() 35 { 36 h=0; t=1; 37 vis[s]=1; 38 q[1]=s; 39 int u,v,d,i,j,k; 40 while (h!=t) 41 { 42 h++; h%=maxn; u=q[h]; 43 for (k=fir[u];k;k=g[k].nex) 44 { 45 v=g[k].u; 46 if (dis[u]+g[k].w<dis[v] && v!=s) 47 { 48 dis[v]=dis[u]+g[k].w; 49 if (!vis[v]) 50 { 51 vis[v]=1; 52 if (dis[v]<dis[q[h+1]]) 53 q[h]=v, 54 h=(h-1+maxn)%maxn; 55 else 56 t++,t%=maxn, 57 q[t]=v; 58 } 59 60 } 61 } 62 vis[u]=0; 63 } 64 return; 65 } 66 int main() 67 { 68 int i,j,k,x,y,z; 69 //scanf("%d%d%d%d",&n,&R,&P,&s); 70 n=read(); R=read(); P=read(); s=read(); 71 for (i=1;i<=R;i++) 72 //scanf("%d%d%d",&x,&y,&z), 73 x=read(),y=read(),z=read(), 74 add(x,y,z),add(y,x,z); 75 for (i=1;i<=P;i++) 76 //scanf("%d%d%d",&x,&y,&z), 77 x=read(),y=read(),z=read(), 78 add(x,y,z); 79 for (i=1;i<=n;i++) dis[i]=1e9; 80 dis[s]=0; 81 spfa(); 82 for (i=1;i<=n;i++) 83 if (dis[i]<1e9) write(dis[i]),printf(" "); 84 else printf("NO PATH "); 85 return 0; 86 }