POJ-3268 Silver Cow Party---正向+反向Dijkstra

题目链接:

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 }
原文地址:https://www.cnblogs.com/fzl194/p/8732687.html