道路和航线(最短路SPFA优化算法)
Posted sylvia11
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了道路和航线(最短路SPFA优化算法)相关的知识,希望对你有一定的参考价值。
道路和航线
时间限制: 1 Sec 内存限制: 128 MB题目描述
Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查。他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T。这些城镇之间通过R条道路 (1 <= R <= 50,000,编号为1到R) 和P条航线 (1 <= P <= 50,000,编号为1到P) 连接。每条道路i或者航线i连接城镇Ai (1 <= Ai <= T)到Bi (1 <= Bi <= T),花费为Ci。对于道路,0 <= Ci <= 10,000;然而航线的花费很神奇,花费Ci可能是负数(-10,000 <= Ci <= 10,000)。道路是双向的,可以从Ai到Bi,也可以从Bi到Ai,花费都是Ci。然而航线与之不同,只可以从Ai到Bi。事实上,由于最近恐怖主义太嚣张,为了社会和谐,出台 了一些政策保证:如果有一条航线可以从Ai到Bi,那么保证不可能通过一些道路和航线从Bi回到Ai。由于FJ的奶牛世界公认十分给力,他需要运送奶牛到每一个城镇。他想找到从发送中心城镇S(1 <= S <= T) 把奶牛送到每个城镇的最便宜的方案,或者知道这是不可能的。
输入
* 第1行:四个空格隔开的整数: T, R, P, and S * 第2到R+1行:三个空格隔开的整数(表示一条道路):Ai, Bi 和 Ci * 第R+2到R+P+1行:三个空格隔开的整数(表示一条航线):Ai, Bi 和 Ci
输出
* 第1到T行:从S到达城镇i的最小花费,如果不存在输出"NO PATH"。
样例输入 Copy
6 3 3 4
1 2 5
3 4 5
5 6 10
3 5 -100
4 6 -100
1 3 -10
样例输出 Copy
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号城镇。
4->6和1->3,花费分别是-100,-100,-10。FJ的中心城镇在城镇4。
FJ的奶牛从4号城镇开始,可以通过道路到达3号城镇。然后他们会通过航线达到5和6号城镇。
但是不可能到达1和2号城镇。
题解:最短路的题 ,直接跑最短路SPFA 的话,会被卡 ,加O3一样会被卡 ,所以 就用SPFA的优化 ,优化有以下几点:
1.将SPFA中的queue队列换成deque双端队列
2. 当队列非空时,判断当前dis[v]与和队首比较 然后将数值小的放在队首,方便快速更新
if
(!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v);
else
q.push_back(v);
3.复习一下SPFA ,加边 初始化head【】=-1
跑SPFA 声明dis【】到原点的距离 vis【】是否在队列中 队列
初始化 n个点 的dis【】=INT_MAX memset vis 为 0
原点加入队列 dis=0 标记vis=1;
跑循环, 从队列取出一个数,遍历点所到达所有边 ,用队列中已经被更新的点,当 dis[v]>dis[now]+edg[i].w 更新其他点,然后加队列标记
1 #pragma GCC optimize(3,"Ofast","inline") 2 #include <bits/stdc++.h> 3 using namespace std; 4 const int N=500000; 5 int n,r,p,s; 6 struct ss 7 { 8 int u,v,w,next; 9 }edg[N]; 10 int sumedg,head[N]; 11 void addedg(int u,int v,int w) 12 { 13 edg[sumedg]=(ss){u,v,w,head[u]}; 14 head[u]=sumedg++; 15 } 16 int dis[N]; 17 bool vis[N]; 18 void spfa() 19 { 20 deque<int>q; 21 for(int i=0;i<n+10;i++) dis[i]=INT_MAX; 22 memset(vis,0,sizeof(vis)); 23 q.push_back(s); 24 vis[s]=1; 25 dis[s]=0; 26 long long sum1=0,sum2=1; 27 28 while(!q.empty()) 29 { 30 int now=q.front();q.pop_front(); 31 32 sum2--; 33 sum1-=dis[now]; 34 35 while(sum2&&sum2*dis[now]>sum1) 36 { 37 q.push_back(now); 38 sum1+=dis[now]; 39 now=q.front(); 40 q.pop_front(); 41 sum1-=dis[now]; 42 } 43 44 vis[now]=0; 45 for(int i=head[now];i!=-1;i=edg[i].next) 46 { 47 int v=edg[i].v; 48 if(dis[v]>dis[now]+edg[i].w) 49 { 50 dis[v]=dis[now]+edg[i].w; 51 if(!vis[v]) 52 { 53 vis[v]=1; 54 if(!q.empty()&&dis[v]<dis[q.front()]) q.push_front(v); 55 else q.push_back(v); 56 57 sum1+=dis[v]; 58 sum2++; 59 } 60 } 61 } 62 } 63 } 64 int main() 65 { 66 scanf("%d%d%d%d",&n,&r,&p,&s); 67 for(int i=0;i<=n;i++) head[i]=-1; 68 for(int i=0;i<r;i++) 69 { 70 int u,v,w; 71 scanf("%d%d%d",&u,&v,&w); 72 addedg(u,v,w); 73 addedg(v,u,w); 74 } 75 for(int i=0;i<p;i++) 76 { 77 int u,v,w; 78 scanf("%d%d%d",&u,&v,&w); 79 addedg(u,v,w); 80 } 81 spfa(); 82 for(int i=1;i<=n;i++) 83 { 84 if(dis[i]!=INT_MAX) printf("%d\n",dis[i]); 85 else printf("NO PATH\n"); 86 } 87 return 0; 88 }
以上是关于道路和航线(最短路SPFA优化算法)的主要内容,如果未能解决你的问题,请参考以下文章