2010年02月10日星期三.sgu185
ALGO:dijkstra + 流
求两条没有相同边的最短路。
直觉的想法是求一条,然后把这条相关的删掉,再求另外一条
但是这种想法是不正确的。
引用
http://www.answeror.com/archives/28474 的一组数据来说明这个问题
6 7
1 2 1
1 3 1
2 4 1
3 4 1
3 5 1
4 6 1
5 6 1
如果第一次求出的最短路是1-3-4-6, 那么第二条最短路就不存在了, 但是实际上有两条最短路,
即1-3-5-6和1-2-4-6.
所以需要调整,调整的思想让我们想到了流。
保留图中所有能构成任何一条最短路的边,将所有边的容量设为1. 然后对这个图求两次增广路。
由于容量的限制,所以求得的两条最短路一定是没有公共边的,这时按照流的方向,输出这两条
路径即可。
注意:不要按照增广时的顶点顺序输出最短路,这样是不对的,同样可以使用上面的那组数据,
如果先增广的是 1-3-4-6这条路径的话,那么输出的结果就会不正确了。 我就是这么wa@test 20 好久的。
1
2 const int N = 401;
3 const int inf = 1 << 20;
4 int dis[N],vis[N],n,m;
5 int g1[N][N],g2[N][N],p[N],f[N][N];
6
7 bool dijkstra()
8 {
9 int i,j,k;
10 memset(vis,0,sizeof(vis));
11 dis[1] = 0,vis[1] = true;
12 for (i = 2;i <= n;i++) {
13 dis[i] = g1[1][i];
14 }
15 for (k = 2;k <= n;k++) {
16 int min = inf,idx = 1;
17 for (i = 2;i <= n;i++) {
18 if (dis[i] < min && !vis[i]) {
19 min = dis[i],idx = i;
20 }
21 }
22 if (idx == 1) { break; }
23 vis[idx] = true;
24 for (i = 1;i <= n;i++) {
25 if (dis[i] > min + g1[idx][i]) {
26 dis[i] = min + g1[idx][i];
27 }
28 }
29 }
30 for (i = 1;i <= n;i++) {
31 for (j = 1;j <= n;j++) {
32 if (dis[i] + g1[i][j] == dis[j]) {
33 g2[i][j] = 1;
34 }
35 }
36 }
37 return dis[n] != inf;
38 }
39
40 bool bfs()
41 {
42 memset(vis,0,sizeof(vis));
43 memset(p,0,sizeof(p));
44 queue<int> que;
45 que.push(1),vis[1] = true;
46 while (!que.empty()) {
47 int u = que.front(); que.pop();
48 for (int v = 2;v <= n;v++) {
49 if (!vis[v] && g2[u][v]) {
50 p[v] = u,vis[v] = true;
51 if (v == n) {
52 for (v = n;v != 1;v = p[v]) {
53 u = p[v];
54 g2[u][v] --;
55 g2[v][u] ++;
56 if (f[v][u] > 0) {
57 f[v][u]--;
58 }else {
59 f[u][v] ++;
60 }
61 }
62 return true;
63 }
64 que.push(v);
65 }
66 }
67 }
68 return false;
69 }
70
71 void pr(int u)
72 {
73 if (u == n) {
74 printf("%d\n",u);
75 return;
76 }
77 for (int i = 1;i <= n;i++) {
78 if (f[u][i] > 0) {
79 f[u][i] --;
80 printf("%d ",u);
81 pr(i);
82 return ;
83 }
84 }
85 }
86
87 bool EK()
88 {
89 if (bfs() && bfs()) {
90 pr(1), pr(1);
91 return true;
92 }
93 return false;
94 }
95
96
97 int main()
98 {
99 int i,j,a,b,c;
100 scanf("%d%d",&n,&m);
101 for (i = 1;i <= n;i++) {
102 for (j = 1;j <= n;j++) {
103 g1[i][j] = inf;
104 }
105 }
106 for (i = 0;i < m;i++) {
107 scanf("%d%d%d",&a,&b,&c);
108 if (g1[a][b] > c) {
109 g1[a][b] = g1[b][a] = c;
110 }
111 }
112 if (!dijkstra() || !EK()){
113 printf("No solution\n");
114 }
115 return 0;
116 }
117