题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=2532
题意:给出一张图,有N个城市,M个中继站,和L条线路连接。
城市发送数据,最终发送到总部(标号为0),问增大哪些线路带宽能够增加总部接收到的带宽。(考虑一条边的时候,增大这条边,别的不能变化)。
思路:
由于时间复杂度,依次把每条边的容量+1,然后求最大流与原来的最大流相比较,这种做法是不可行的。
考虑最大流算法,是不停地找增广路。
那么如果一条边u->v,如果从源点开始不停找增广路,能够找到点u。
从汇点开始反向找增广路,能够找到点v,且u->v满流,那么只要增加这条边的容量,就可以增加最大流,符合题目中的条件。
由于有多个城市,先设立一个超级源点s,连边到每个城市,容量为正无穷。
然后把原图中给出的边在图中连接起来,容量即给出的对应值。
把0号设为汇点。然后求最大流。
再分别就源点和汇点dfs找出源点增广路能够到达的点from[u] = 1,和汇点增广路能够到达的点to[v] = 1。注意反向找边的时候,判断满流的条件是判断其对应的正向边是否满流。
检查残量网络中的边,设为u->v,如果这条边满流,且from[u]=1,to[v]=1,则这条边满足条件。
1 #include <bits/stdc++.h> 2 using namespace std; 3 #define maxn 110 4 const int inf = 0x3f3f3f3f; 5 int N, M, L; 6 struct Edge 7 { 8 int from, to, cap, flow, id; 9 Edge(int f, int t, int c, int fl, int i) 10 { 11 from = f; to = t; cap = c; flow = fl; id = i; 12 } 13 }; 14 int from[maxn], to[maxn]; 15 int n, m, s, t; 16 vector <Edge> edges; 17 vector <int> G[maxn]; 18 int vis[maxn], cur[maxn], d[maxn]; 19 void AddEdge(int from, int to, int cap, int id) 20 { 21 edges.push_back(Edge(from, to, cap, 0, id)); 22 edges.push_back(Edge(to, from, 0, 0, -1)); 23 m = edges.size(); 24 G[from].push_back(m-2); 25 G[to].push_back(m-1); 26 } 27 bool bfs() 28 { 29 memset(vis, 0, sizeof(vis)); 30 vis[s] = 1; 31 d[s] = 0; 32 queue <int> q; 33 q.push(s); 34 while(!q.empty()) 35 { 36 int u = q.front(); 37 q.pop(); 38 for(int i = 0; i < G[u].size(); i++) 39 { 40 Edge &e = edges[G[u][i]]; 41 if(!vis[e.to] && e.cap > e.flow) 42 { 43 vis[e.to] = 1; 44 d[e.to] = d[u] + 1; 45 q.push(e.to); 46 } 47 } 48 } 49 return vis[t]; 50 } 51 int dfs(int x, int a) 52 { 53 if(x == t || a == 0) return a; 54 int flow = 0, f; 55 for(int &i = cur[x]; i < G[x].size(); i++) 56 { 57 Edge &e = edges[G[x][i]]; 58 if(d[x]+1 == d[e.to] && (f = dfs(e.to, min(e.cap-e.flow, a))) > 0) 59 { 60 e.flow += f; 61 edges[G[x][i]^1].flow -= f; 62 flow += f; 63 a -= f; 64 if(a == 0) break; 65 } 66 } 67 return flow; 68 } 69 int MaxFlow() 70 { 71 int flow = 0; 72 while(bfs()) 73 { 74 memset(cur, 0, sizeof(cur)); 75 flow += dfs(s, inf); 76 } 77 return flow; 78 } 79 void dfsfrom(int fa) 80 { 81 from[fa] = 1; 82 for(int i = 0; i < G[fa].size(); i++) 83 { 84 Edge &e = edges[G[fa][i]]; 85 if(e.id == -1) continue; //反向边 86 if(from[e.to]) continue; //已经访问过 87 if(e.cap == e.flow) continue; //满流 88 dfsfrom(e.to); 89 } 90 } 91 void dfsto(int fa) 92 { 93 to[fa] = 1; 94 for(int i = 0; i < G[fa].size(); i++) 95 { 96 Edge &e = edges[G[fa][i]]; 97 if(e.id != -1) continue; //反向边 98 if(edges[G[fa][i]-1].cap == edges[G[fa][i]-1].flow) continue; //满流 99 if(to[e.to]) continue; //已经访问过 100 dfsto(e.to); 101 } 102 } 103 int main() 104 { 105 while(scanf("%d%d%d", &N,&M,&L) && N) 106 { 107 t = 0; s = N+M+1; 108 edges.clear(); 109 for(int i = 0; i <= N+M+1; i++) G[i].clear(); 110 111 for(int i = 1; i <= L; i++) 112 { 113 int a, b, c; 114 scanf("%d%d%d", &a, &b, &c); 115 AddEdge(a, b, c, i); 116 } 117 for(int i = 1; i <= N; i++) AddEdge(s, i, inf, -2); 118 119 int flow = MaxFlow(); 120 memset(from, 0, sizeof(from)); 121 memset(to, 0, sizeof(to)); 122 dfsfrom(s); 123 dfsto(t); 124 125 bool flag = true; 126 for(int i = 0; i < 2*L; i += 2) 127 { 128 if(edges[i].cap == edges[i].flow 129 && from[edges[i].from] && to[edges[i].to]) 130 { 131 if(flag){flag = false; printf("%d", edges[i].id);} 132 else printf(" %d", edges[i].id); 133 } 134 } 135 printf(" "); 136 137 } 138 return 0; 139 }