题目链接:
https://vjudge.net/problem/POJ-3268
题目大意:
有编号为1-N的牛,它们之间存在一些单向的路径。给定一头牛的编号X,其他牛要去拜访它并且拜访完之后要返回自己原来的位置,求所有牛从开始到回家的时间是多少?
思路:
所有牛都回到了家所花费的时间就是这些牛中花费时间的最大者,可以正向的Dijkstra求出从X到每个点的最短时间,然后一个骚操作:将所有边反向(swap(Map[i][j], Map[j][i])),再从x用dijkstra求出X到每个点的最短时间,第二次求出来的时间通过逆向求出来的是每个点到X的最短时间,两个一加,取最大者就是答案。
本题也可以用Bellman来求,不过由于边比较多,必须用队列优化的SPFA来求,但是SPA需要邻接表,不能像邻接矩阵那样直接反向,所以存图的时候存两张图,一张正向,一张反向,跑俩遍出结果。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<cmath> 6 #include<queue> 7 #include<stack> 8 #include<map> 9 #include<set> 10 #include<sstream> 11 using namespace std; 12 typedef long long ll; 13 const int maxn = 1000 + 10; 14 const int INF = 1e9 + 7; 15 int T, n, m, cases; 16 int Map[maxn][maxn]; 17 int d1[maxn], d2[maxn]; 18 bool v[maxn]; 19 void flip() 20 { 21 for(int i = 1; i <= n; i++) 22 { 23 for(int j = i + 1; j <= n; j++)swap(Map[i][j], Map[j][i]); 24 } 25 } 26 void dijkstra(int u, int d[]) 27 { 28 memset(v, 0, sizeof(v)); 29 for(int i = 0; i <= n; i++)d[i] = INF; 30 d[u] = 0; 31 for(int i = 1; i <= n; i++) 32 { 33 int x, m = INF; 34 for(int i = 1; i <= n; i++)if(!v[i] && d[i] <= m)m = d[x = i];//找距离源点最近的点 35 v[x] = 1; 36 for(int i = 1; i <= n; i++)d[i] = min(d[i], d[x] + Map[x][i]);//进行松弛 37 } 38 } 39 int main() 40 { 41 int u, x, y, z; 42 while(cin >> n >> m >> u) 43 { 44 for(int i = 0; i <= n; i++) 45 for(int j = 0; j <= n; j++)Map[i][j] = (i == j ? 0 : INF); 46 for(int i = 0; i < m; i++) 47 { 48 scanf("%d%d%d", &x, &y, &z); 49 //cout<<"000"<<endl; 50 Map[x][y] = z; 51 } 52 dijkstra(u, d1); 53 flip(); 54 dijkstra(u, d2); 55 for(int i = 1; i <= n; i++)d1[i] += d2[i]; 56 sort(d1 + 1, d1 + n + 1); 57 cout<<d1[n]<<endl; 58 } 59 return 0; 60 }