题目:
问题描述:
John Farmer的牧场有n(1n1,000)头奶牛,分别住在对应编号1..n的牧场。将参加编号X(1Xn) 的奶牛牧场聚会。总共m(1m100,000)条单向道路连接成对的牧场;第i条道路需要Ti(1Ti100)单位时间。
每头奶牛都必须走到聚会,聚会结束后再返回到自己的牧场。每头奶牛都要选择一条最短路线。因为是单向道路,奶牛的回程路线可能与来时不同,所有奶牛都选择最短路线往返,请找出奶牛中花费最长的时间?
输入格式:
第1行: 三个整数n(1n1,000) 头奶牛,m(1m50,000)条单向道路,将参加编号X(1Xn)奶牛牧场的聚会。
第2…m+1行: 第i+1行三个整数描述第i条单向道路,Ai,Bi表示一条道路从Ai到Bi,需要Ti(1Ti100)单位时间。
输出格式:
仅1行1个整数,表示奶牛中花费最长的时间。
输入输出样例:
sparty.in
4 8 2 1 2 4 1 3 2 1 4 7 2 1 1 2 3 5 3 1 2 3 4 4 4 2 3
sparty.out
10
输入输出解释:
总共有4头牛;8条单向道路,在编号2的牧场聚会。奶牛1往返4+1=5;奶牛2往返0;奶牛3往返2+4+1+2=9;奶牛4往返3+1+2+4=10时间最长,输出10。
程序:
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 5 int n,m,p,i,j,t[50005],k[50005],s[50005],Head[1005],f1[1005],f[1005]; 6 bool flag[1005]; 7 struct edge 8 { 9 int Next,Weight,Aim; 10 }Edge[50005]; 11 12 void add(int u,int v,int w,int x) 13 { 14 Edge[x].Next=Head[u]; 15 Head[u]=x; 16 Edge[x].Weight=w; 17 Edge[x].Aim=v; 18 } 19 20 void SPFA() 21 { 22 int i; 23 queue<int> Q; 24 memset(flag,0,sizeof(flag)); 25 memset(f,0x3f3f3f3f,sizeof(f)); 26 flag[p]=1;f[p]=0; 27 Q.push(p); 28 while (!Q.empty()) 29 { 30 int t=Q.front(); 31 Q.pop(); 32 flag[t]=0; 33 for (i=Head[t];i;i=Edge[i].Next) 34 if (f[Edge[i].Aim]>Edge[i].Weight+f[t]) 35 { 36 f[Edge[i].Aim]=Edge[i].Weight+f[t]; 37 if (flag[Edge[i].Aim]==0) 38 { 39 Q.push(Edge[i].Aim); 40 flag[Edge[i].Aim]=1; 41 } 42 } 43 } 44 } 45 46 int main() 47 { 48 freopen("sparty.in","r",stdin); 49 freopen("sparty.out","w",stdout); 50 cin>>n>>m>>p; 51 for (i=1;i<=m;i++) 52 cin>>t[i]>>k[i]>>s[i]; 53 for (i=1;i<=m;i++) 54 add(t[i],k[i],s[i],i); 55 SPFA(); 56 for (i=1;i<=n;i++) 57 f1[i]=f[i]; 58 memset(Head,0,sizeof(Head)); 59 for (i=1;i<=m;i++) 60 add(k[i],t[i],s[i],i); 61 SPFA(); 62 int ans=0; 63 for (i=1;i<=n;i++) 64 ans=max(ans,f[i]+f1[i]); 65 cout<<ans<<endl; 66 return 0; 67 }
分析:
这道题目显然就是一个单源最短路。先按照原图从聚会的地方往牧场的方向跑SPFA,然后反过来从牧场的方向往聚会的地方跑SPFA。
简单分析一下SPFA的原理。
简单来说SPFA的形式和广度优先搜索(BFS)有些类似。首先建立一个队列Q,队列中存储的是所有待处理的点。在队列非空时开始循环,弹出队首元素存入t,然后循环所有以为开始节点的边。如果当前循环的边的终点的最短路长度可以更新,那么就更新它(废话)。这个点的值被更新过以后,意味着这条边的终点也成为了一个需要处理的点。如果它现在不在队列中,把它加入队列,作为一个需要处理的点。SPFA:
procedure Shortest-Path-Faster-Algorithm(G, s) 1 for each vertex v ≠ s in V(G) 2 d(v) := ∞ 3 d(s) := 0 4 offer s into Q 5 while Q is not empty 6 u := poll Q 7 for each edge (u, v) in E(G) 8 if d(u) + w(u, v) < d(v) then 9 d(v) := d(u) + w(u, v) 10 if v is not in Q then 11 offer v into Q