http://poj.org/problem?id=2135
题意:约翰要带朋友参观农场。农场里有N块地,M条双向路径。第i条路连接ai和bi两块地,长度为ci。约翰住在一号地,他想带朋友们参观一圈,但每条路只能走一次。求路线的最小值。
题解:转换为求从1号到N号顶点的两条没有公共边的路径,就变成了最小费用流问题。因为涉及到往返,流量应该设为2。
求最小费用流的时候用Bellman_Ford求最短路效率要慢,改进后的Dijkstra要快。可是我交了之后发现Bellman_Ford用了32MS,Dijkstra要用47MS……
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cmath> 6 #include <string> 7 #include <vector> 8 #include <list> 9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <bitset> 13 #include <algorithm> 14 #include <numeric> 15 #include <functional> 16 #include <set> 17 #include <fstream> 18 19 using namespace std; 20 21 const int maxn=10010; 22 const int INF=0x7fffffff; 23 int N,M; 24 int a[maxn],b[maxn],c[maxn]; 25 struct edge { 26 int to,cap,cost,rev; 27 }; 28 int V; 29 vector<edge> G[maxn]; 30 int dist[maxn]; 31 int prevv[maxn],preve[maxn]; 32 /* 33 void add_edge(int from,int to,int cap,int cost) 34 { 35 G[from].push_back((edge){to,cap,cost,(int)G[to].size()}); 36 G[to].push_back((edge){from,0,-cost,(int)G[from].size()-1}); 37 } 38 39 int min_cost_flow(int s,int t,int f) 40 { 41 int res=0; 42 while (f>0) { 43 fill(dist, dist+V, INF); 44 dist[s]=0; 45 bool update=true; 46 while (update) { 47 update=false; 48 for (int v=0; v<V; v++) { 49 if (dist[v]==INF) { 50 continue; 51 } 52 for (int i=0; i<G[v].size(); i++) { 53 edge &e=G[v][i]; 54 if (e.cap>0&&dist[e.to]>dist[v]+e.cost) { 55 dist[e.to]=dist[v]+e.cost; 56 prevv[e.to]=v; 57 preve[e.to]=i; 58 update=true; 59 } 60 } 61 } 62 } 63 if (dist[t]==INF) { 64 return -1; 65 } 66 int d=f; 67 for (int v=t; v!=s; v=prevv[v]) { 68 d=min(d,G[prevv[v]][preve[v]].cap); 69 } 70 f-=d; 71 res+=d*dist[t]; 72 for (int v=t; v!=s; v=prevv[v]) { 73 edge &e=G[prevv[v]][preve[v]]; 74 e.cap-=d; 75 G[v][e.rev].cap+=d; 76 } 77 } 78 return res; 79 } 80 */ 81 int h[maxn]; 82 typedef pair<int, int> P; 83 void add_edge(int from,int to,int cap,int cost) 84 { 85 G[from].push_back((edge){to,cap,cost,(int)G[to].size()}); 86 G[to].push_back((edge){from,0,-cost,(int)G[from].size()-1}); 87 } 88 89 int min_cost_flow(int s,int t,int f) 90 { 91 int res=0; 92 fill(h, h+V, 0); 93 while (f>0) { 94 priority_queue<P,vector<P>,greater<P> > que; 95 fill(dist, dist+V, INF); 96 dist[s]=0; 97 que.push(P(0,s)); 98 while (!que.empty()) { 99 P p=que.top(); 100 que.pop(); 101 int v=p.second; 102 if (dist[v]<p.first) { 103 continue; 104 } 105 for (int i=0; i<G[v].size(); i++) { 106 edge &e=G[v][i]; 107 if (e.cap>0&&dist[e.to]>dist[v]+e.cost+h[v]-h[e.to]) { 108 dist[e.to]=dist[v]+e.cost+h[v]-h[e.to]; 109 prevv[e.to]=v; 110 preve[e.to]=i; 111 que.push(P(dist[e.to],e.to)); 112 } 113 } 114 } 115 if (dist[t]==INF) { 116 return -1; 117 } 118 for (int v=0; v<V; v++) { 119 h[v]+=dist[v]; 120 } 121 int d=f; 122 for (int v=t; v!=s; v=prevv[v]) { 123 d=min(d,G[prevv[v]][preve[v]].cap); 124 } 125 f-=d; 126 res+=d*h[t]; 127 for (int v=t; v!=s; v=prevv[v]) { 128 edge &e=G[prevv[v]][preve[v]]; 129 e.cap-=d; 130 G[v][e.rev].cap+=d; 131 } 132 } 133 return res; 134 } 135 136 int main() 137 { 138 //freopen("/Users/apple/Desktop/2135/2135/in", "r", stdin); 139 //freopen("/Users/apple/Desktop/2135/2135/out", "w", stdout); 140 while ((scanf("%d%d",&N,&M))!=EOF) { 141 V=N; 142 for (int i=0; i<M; i++) { 143 scanf("%d%d%d",&a[i],&b[i],&c[i]); 144 } 145 int s=0,t=N-1; 146 for (int i=0; i<M; i++) { 147 add_edge(a[i]-1, b[i]-1, 1, c[i]); 148 add_edge(b[i]-1, a[i]-1, 1, c[i]); 149 } 150 int res2=min_cost_flow(s, t, 2); 151 printf("%d ",res2); 152 } 153 return 0; 154 }