ZOJ 2532 Internship 网络流求关键边

题目链接: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 }
原文地址:https://www.cnblogs.com/titicia/p/4857058.html