题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=21068
Yesterday Vasya and Petya quarreled badly, and now they don't want to see each other on their way to school. The problem is that they live in one and the same house, leave the house at the same time and go at the same speed by the shortest road. Neither of them wants to change their principles, that is why they want to find two separate shortest routes, which won't make them go along one road, but still they can meet at any junction. They ask you to help them. They number all the junctions with numbers from 1 to N (home and school are also considered as junctions). So their house has the number 1 and the school has the number N, each road connects two junctions exactly, and there cannot be several roads between any two junctions.
题意描述:有n个节点,找出1~n的两条不相交的最短路(两条路径可以共点不能共边)。
算法分析:用spfa求出点1到各个点的最短路径,然后再if(d[j]==d[i]+dis[i][j]) 来判断边dis[i][j]是否是在最短路径上,如果是就加到图里,结果就得到以1为顶点的最短路径树,1到树中任意一点的连线都是最短路径,首先把这些边加到网络流的边集中,容量为1。跑一遍1到n的最大流,如果流量>=2则有解,再从原点深搜路径即可。
说明:这道题很卡内存和时间,MLE!MLE!MLE!M出翔了。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<cmath> 6 #include<algorithm> 7 #include<queue> 8 #include<vector> 9 #define inf 10737418 10 using namespace std; 11 typedef long long ll; 12 const int maxn=400+10; 13 const int M = 120000+10; 14 15 int n,m,from,to; 16 struct Edge 17 { 18 int to,cap; 19 int next; 20 }edge[M*2]; 21 int head[maxn],edgenum; 22 23 void add(int u,int v,int cap) 24 { 25 Edge E={v,cap,head[u]}; 26 edge[edgenum]=E; 27 head[u]=edgenum++; 28 29 Edge E2={u,0,head[v]}; 30 edge[edgenum]=E2; 31 head[v]=edgenum++; 32 } 33 34 int d[maxn]; 35 bool BFS() 36 { 37 memset(d,-1,sizeof(d)); 38 d[from]=0; 39 queue<int> Q; 40 Q.push(from); 41 while (!Q.empty() ){ 42 int u=Q.front(); Q.pop(); 43 for (int i=head[u] ;i!=-1 ;i=edge[i].next) 44 { 45 int v=edge[i].to; 46 if (d[v]==-1 && edge[i].cap) 47 { 48 d[v]=d[u]+1,Q.push(v); 49 if (d[to] != -1) return true; 50 } 51 } 52 } 53 return false; 54 } 55 int Stack[maxn], top, cur[maxn]; 56 int Dinic(){ 57 int ans=0; 58 while(BFS()) 59 { 60 memcpy(cur, head, sizeof(head)); 61 int u = from; top = 0; 62 while(1) 63 { 64 if(u == to) 65 { 66 int flow = inf, loc;//loc 表示 Stack 中 cap 最小的边 67 for(int i = 0; i < top; i++) 68 if(flow > edge[ Stack[i] ].cap) 69 { 70 flow = edge[Stack[i]].cap; 71 loc = i; 72 } 73 74 for(int i = 0; i < top; i++) 75 { 76 edge[ Stack[i] ].cap -= flow; 77 edge[Stack[i]^1].cap += flow; 78 } 79 ans += flow; 80 top = loc; 81 u = edge[Stack[top]^1].to; 82 } 83 for(int i = cur[u]; i!=-1; cur[u] = i = edge[i].next)//cur[u] 表示u所在能增广的边的下标 84 if(edge[i].cap && (d[u] + 1 == d[ edge[i].to ]))break; 85 if(cur[u] != -1) 86 { 87 Stack[top++] = cur[u]; 88 u = edge[ cur[u] ].to; 89 } 90 else 91 { 92 if( top == 0 )break; 93 d[u] = -1; 94 u = edge[ Stack[--top]^1 ].to; 95 } 96 } 97 } 98 return ans; 99 } 100 int dis[maxn][maxn]; 101 int vis[maxn]; 102 void spfa() 103 { 104 for (int i=1 ;i<=n ;i++) d[i]=inf; 105 d[1]=0; 106 memset(vis,0,sizeof(vis)); 107 queue<int> Q; 108 Q.push(1); 109 vis[1]=1; 110 while (!Q.empty()) 111 { 112 int u=Q.front() ;Q.pop() ; 113 vis[u]=0; 114 for (int v=1 ;v<=n ;v++) 115 { 116 if (d[v]>d[u]+dis[u][v]) 117 { 118 d[v]=d[u]+dis[u][v]; 119 if (!vis[v]) 120 { 121 vis[v]=1; 122 Q.push(v); 123 } 124 } 125 } 126 } 127 } 128 void dfs(int u, int fa) 129 { 130 if (u == n){printf("%d ",u);return ;} 131 else printf("%d ",u); 132 for (int i = head[u] ;i!=-1 ;i=edge[i].next) 133 { 134 if (edge[i^1].cap != 1 || (i&1)) continue; 135 int v=edge[i].to; 136 if (v == fa) continue; 137 edge[i^1].cap=0; 138 dfs(v, u); 139 return; 140 } 141 } 142 143 int main() 144 { 145 while (scanf("%d%d",&n,&m)!=EOF) 146 { 147 memset(head,-1,sizeof(head)); 148 edgenum=0; 149 int a,b,c; 150 for (int i=1 ;i<=n ;i++) 151 for (int j=1 ;j<=n ;j++) 152 dis[i][j]=inf; 153 for (int i=0 ;i<m ;i++) 154 { 155 scanf("%d%d%d",&a,&b,&c); 156 dis[a][b] = dis[b][a] = min(dis[a][b], c); 157 } 158 spfa(); 159 if (d[n]==inf) {printf("No solution ");continue; } 160 from=1; 161 to=n+1; 162 for (int i=1 ;i<=n ;i++) 163 { 164 for (int j=1 ;j<=n ;j++) 165 { 166 if(dis[i][j]!=inf && d[j] == dis[i][j] + d[i]) 167 add(i,j,1); 168 } 169 } 170 add(n,to,2); 171 int sum=Dinic(); 172 if (sum<2) {printf("No solution ");continue; } 173 dfs(1,1); 174 dfs(1,1); 175 } 176 return 0; 177 }