道路和航线
试题描述
|
Farmer John 正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到 T (1≤T≤2.5×10^4)个城镇 ,编号为 1 到 T。这些城镇之间通过 R 条道路(编号为 1 到 R)和 P 条航线(编号为 1 到 P)连接。每条道路 i 或者航线 i 连接城镇 Ai到 Bi,花费为 Ci。
对于道路,0≤Ci≤104,然而航线的花费很神奇,花费 Ci可能是负数。道路是双向的,可以从 Ai到 Bi,也可以从 Bi到 Ai,花费都是 Ci。然而航线与之不同,只可以从 Ai到 Bi。 事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台了一些政策保证:如果有一条航线可以从 Ai到 Bi,那么保证不可能通过一些道路和航线从 Bi回到 Ai。由于 FJ 的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇 S 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。 |
输入
|
第一行为四个空格隔开的整数:T,R,P,S;
第二到第 R+1 行:三个空格隔开的整数(表示一条道路):Ai,Bi和 Ci; 第 R+2 到 R+P+1行:三个空格隔开的整数(表示一条航线):Ai,Bi和 Ci。 |
输出
|
输出 T 行,第 i 行表示到达城镇 i 的最小花费,如果不存在输出 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 |
其他说明
|
样例说明
一共六个城镇。在 1 和 2,3 和 4,5 和 6 之间有道路,花费分别是 5,5,10。同时有三条航线:3→5,4→6 和 1→3,花费分别是 −100,−100,−10。FJ 的中心城镇在城镇 4。FJ 的奶牛从 4 号城镇开始,可以通过道路到达 3 号城镇。然后他们会通过航线达到 5 和 6 号城镇。但是不可能到达 1 和 2 号城镇。 数据范围与提示 对于全部数据,1≤T≤2.5×10^4,1≤R,P≤5×10^4,1≤Ai,Bi,S≤T。保证对于所有道路,0≤Ci≤10^4,对于所有航线,−10^4≤Ci≤10^4。 |
一个很明显的板子题,SPFA要加一点优化,否则会T
具体的优化被称作SLF:
利用一个双端队列,比较即将插入队首的和队首的dis值,如果比队首小,就加到队首,否则直接放到队尾
可以减少一些无用的状态
下面给出代码
#include<iostream> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<queue> using namespace std; int rd() { int x=0,f=1; char ch=getchar(); for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; return x*f; } void write(int x) { if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); return ; } int head[1000006],nxt[25001*6],to[25001*6],v[25001*6]; int T,n,m,s; int total=0; void add(int x,int y,int z) { total++; v[total]=z; to[total]=y; nxt[total]=head[x]; head[x]=total; return ; } int book[250001]; int dis[250001]; deque <int> q; void spfa()//SPFA模板 { book[s]=1; q.push_back(s); dis[s]=0; while(!q.empty()) { int h=q.front(); q.pop_front(); book[h]=0; for(int e=head[h];e;e=nxt[e]) { if(dis[to[e]]>dis[h]+v[e]) { dis[to[e]]=dis[h]+v[e]; if(!book[to[e]]) { book[to[e]]=1; if(!q.empty()&&dis[q.front()]>dis[to[e]]) q.push_front(to[e]);//如果大于队首,则放到队首 else q.push_back(to[e]);//放到队尾 } } } } return ; } int main() { T=rd(); n=rd(); m=rd(); s=rd(); for(int i=1;i<=n;i++)//读入道路 { int x,y; int z; x=rd(); y=rd(); z=rd(); add(x,y,z); add(y,x,z); } for(int i=1;i<=m;i++)//读入航线 { int x,y,z; x=rd(); y=rd(); z=rd(); add(x,y,z); } for(int i=1;i<=T;i++) dis[i]=1299999999; spfa(); for(int i=1;i<=T;i++) { if(dis[i]==1299999999) printf("NO PATH\n"); else printf("%d\n",dis[i]); } return 0; }
蒟蒻总是更懂你✿✿ヽ(°▽°)ノ✿