【题意】:在一个网络里面,问增大哪条边的容量可以使整个网络的流量增大,求有多少条这样的边?

【题解】:显然我们要找的边是在最小割集的边,但在最小割集的边不一定都满足条件。例如,s->1->2->t,假如每条边的容量都是5,显然任意一条边都是一个最小割集,但增加哪一条边都不会使网络的流量增加。因此我们找的割边还需要满足一个条件:假如有割边<u,v>,源点s必须可以从残量网络到达u,并且v可以从残量网络到达汇点t。那么增加<u,v>的容量必定有新流量可以沿s->u->v->t增加。具体做法:先求一次最大流,然后从s遍历残量网络,可到达的顶点染色为1;从t沿着反残量网络遍历,可到达的顶点染色为2。然后枚举每条边,如果两端点有色且染色不同,那么该边就是我们要找的关键割边了。其实,枚举边的时候只需枚举满流的边,因为满流的边才能是最小割集的边。

【代码】:
  1 #include "iostream"
  2 #include "cstdio"
  3 #include "vector"
  4 #include "queue"
  5 using namespace std;
  6 #define maxn 505
  7 #define maxm 50005
  8 const int INF = 99999999;
  9 int n, m, s, t;
 10 int eh[maxn], pre[maxn], cur[maxn], dist[maxn], cnt[maxn], color[maxn], tot, low[maxn], ans;
 11 vector<int> vecs[maxn], vect[maxn];
 12 queue<int> que;
 13 struct Edge {
 14     int u, v, cap, flow, next;
 15 }et[maxm];
 16 
 17 void init() {
 18     tot = ans = 0;
 19     memset(eh, -1sizeof(eh));
 20     memset(color, 0sizeof(color));
 21 }
 22 
 23 void add(int u, int v, int cap, int flow) {
 24     Edge e = {u, v, cap, flow, eh[u]};
 25     et[tot] = e;
 26     eh[u] = tot++;
 27 }
 28 
 29 void addedge(int u, int v, int cap) {
 30     add(u, v, cap, 0), add(v, u, 00);
 31 }
 32 
 33 void isap(int s, int t, int n) {
 34     int u, v, now, flow = 0;
 35     memset(dist, 0sizeof(dist));
 36     memset(low, 0sizeof(low));
 37     memset(cnt, 0sizeof(cnt));
 38     for(u = 0; u <= n; u++) cur[u] = eh[u];
 39     low[s] = INF, cnt[0= n;
 40     u = s;
 41     while(dist[s] < n) {
 42         for(now = cur[u]; now != -1; now = et[now].next) {
 43             if(et[now].cap - et[now].flow && dist[u] == dist[v = et[now].v] + 1break;
 44         }
 45         if(now != -1) {
 46             cur[u] = pre[v] = now;
 47             low[v] = min(low[u], et[now].cap - et[now].flow);
 48             u = v;
 49             if(u == t) {
 50                 for(; u != s; u = et[pre[u]].u) {
 51                     et[pre[u]].flow += low[t];
 52                     et[pre[u]^1].flow -= low[t];
 53                 }
 54                 low[s] = INF, flow += low[t];
 55             }
 56         } else {
 57             if(--cnt[dist[u]] == 0break;
 58             dist[u] = n;
 59             cur[u] = eh[u];
 60             for(now = eh[u]; now != -1; now = et[now].next)
 61                 if(et[now].cap - et[now].flow && dist[u] > dist[et[now].v] + 1)
 62                     dist[u] = dist[et[now].v] + 1;
 63                 cnt[dist[u]]++;
 64                 if(u != s) u = et[pre[u]].u;
 65         }
 66     }
 67 }
 68 
 69 void dfs1(int u) {
 70     color[u] = 1;
 71     int size = vecs[u].size();
 72     for(int i = 0; i < size; i++) {
 73         int v = vecs[u][i];
 74         if(!color[v]) dfs1(v);
 75     }
 76 }
 77 
 78 void dfs2(int u) {
 79     color[u] = 2;
 80     int size = vect[u].size();
 81     for(int i = 0; i < size; i++) {
 82         int v = vect[u][i];
 83         if(!color[v]) dfs2(v);
 84     }
 85 }
 86 
 87 int main() {
 88     int i, u, v, cap;
 89     scanf("%d%d"&n, &m);
 90     init();
 91     for(i = 0; i < m; i++) {
 92         scanf("%d%d%d"&u, &v, &cap);
 93         if(cap) addedge(u, v, cap);
 94     }
 95     s = 0, t = n - 1;
 96     isap(s, t, n);
 97     for(i = 0; i < maxn; i++) vecs[i].clear(), vect[i].clear();
 98     for(i = 0; i < tot; i += 2) {
 99         if(et[i].cap - et[i].flow) {
100             u = et[i].u, v = et[i].v;
101             vecs[u].push_back(v);
102             vect[v].push_back(u);
103         } else que.push(i);
104     }
105     dfs1(s), dfs2(t);
106     while(!que.empty()) {
107         i = que.front();
108         que.pop();
109         u = et[i].u, v = et[i].v;
110         if(color[u] == 1 && color[v] == 2) ans++;
111     }
112     cout << ans << endl;
113     return 0;
114 }
115