POJ 3204 Ikki's Story I - Road Reconstruction

题意:给出一个流网络,问有仅将一条边的容量增大可以使得最大流增大的边有多少条。

首先,肯定将是满流的边的容量增大才可能使得最大流增大。但是这些满流的边不一定能是最小割,即使它出现在最小割中,把它的容量增大也不一定能使最大流增大。那么考虑一下求完最大流后不能增广的原因,或者说,怎么样才能在残量网络中增广呢?从S出发,dfs出所有满流的正向边,给dfs经过的点标上f1。再从T出发,逆向dfs出所有满流的边,给dfs经过的点标上f2。那么如果有一条边是这样的:满流且有f1标记和f2标记,那么增加它的容量,残量网络就又可以增广了,最大流会增加,因此这样的边就是我们需要寻找的边。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #define INF 1<<30
  6 #define maxn 510
  7 #define maxm 100000
  8 using namespace std;
  9 
 10 int u[maxm],v[maxm],next[maxm],w[maxm];
 11 int first[maxn],d[maxn],work[maxn],q[maxn];
 12 int e,S,T;
 13 bool f1[maxn],f2[maxn];
 14 int n,m;
 15 void init(){
 16     memset(first,-1,sizeof(first));
 17     e = 0;
 18 }
 19 
 20 void add_edge(int a,int b,int c){
 21     u[e] = a;v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
 22     u[e] = b;v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
 23 }
 24 
 25 int bfs(){
 26     int rear = 0;
 27     memset(d,-1,sizeof(d));
 28     d[S] = 0;q[rear++] = S;
 29     for(int i = 0;i < rear;i++){
 30         for(int j = first[q[i]];j != -1;j = next[j])
 31             if(w[j] && d[v[j]] == -1){
 32                 d[v[j]] = d[q[i]] + 1;
 33                 q[rear++] = v[j];
 34                 if(v[j] == T)   return 1;
 35             }
 36     }
 37     return 0;
 38 }
 39 
 40 int dfs(int cur,int a){
 41     if(cur == T)    return a;
 42     for(int &i = work[cur];i != -1;i = next[i])
 43         if(w[i] && d[v[i]] == d[cur] + 1)
 44             if(int t = dfs(v[i],min(a,w[i]))){
 45                 w[i] -= t;w[i^1] += t;
 46                 return t;
 47             }
 48     return 0;
 49 }
 50 
 51 int dinic(){
 52     int ans = 0;
 53     while(bfs()){
 54         memcpy(work,first,sizeof(first));
 55         while(int t = dfs(S,INF))   ans += t;
 56     }
 57     return ans;
 58 }
 59 
 60 void dfs1(int u){
 61     f1[u] = 1;
 62     for(int i = first[u];i != -1;i = next[i]){
 63         if(!f1[v[i]] && w[i])   dfs1(v[i]);
 64     }
 65 }
 66 
 67 void dfs2(int u){
 68     f2[u] = 1;
 69     for(int i = first[u];i != -1;i = next[i]){
 70         if(!f2[v[i]] && w[i^1]) dfs2(v[i]);
 71     }
 72 }
 73 
 74 int solve(){
 75     memset(f1,0,sizeof(f1));
 76     memset(f2,0,sizeof(f2));
 77     dfs1(S);
 78     dfs2(T);
 79     int ret = 0;
 80     for(int i = 0;i < e;i += 2){
 81         if(f1[u[i]] && f2[v[i]] && !w[i])
 82             ret++;
 83     }
 84     return ret;
 85 }
 86 
 87 int main()
 88 {
 89     init();
 90     int n,m;
 91     scanf("%d%d",&n,&m);
 92     S = 0,T = n-1;
 93     for(int i = 0;i < m;i++){
 94         int a,b,c;
 95         scanf("%d%d%d",&a,&b,&c);
 96         add_edge(a,b,c);
 97     }
 98     dinic();
 99     printf("%d\n",solve());
100     return 0;
101 }
View Code

 

posted @ 2013-11-10 22:18  浙西贫农  阅读(198)  评论(0编辑  收藏  举报