求一次最小割,dfs一遍,然后对每一个满流且是正向边的做一次检查,如果这条边的终点能够到达汇点,则说明可以拓宽这条边来改进网络。

View Code
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=1000,M=10000;
  6 const int inff=1<<29;
  7 int head[N],nc;
  8 struct edge
  9 {
 10     int x,y,next;
 11     int cap;
 12 } edge[M*3];
 13 void add(int x,int y,int cap)
 14 {
 15     edge[nc].x=x;
 16     edge[nc].y=y;
 17     edge[nc].cap=cap;
 18     edge[nc].next=head[x];
 19     head[x]=nc++;
 20     edge[nc].x=y;
 21     edge[nc].y=x;
 22     edge[nc].cap=0;
 23     edge[nc].next=head[y];
 24     head[y]=nc++;
 25 }
 26 int num[N],h[N],S,T,n;
 27 int findpath(int x,int flow)
 28 {
 29     if(x==T)
 30         return flow;
 31     int res=flow,pos=n-1;
 32     for(int i=head[x]; i!=-1; i=edge[i].next)
 33     {
 34         int y=edge[i].y;
 35         if(h[x]==h[y]+1&&edge[i].cap>0)
 36         {
 37             int tp=findpath(y,min(edge[i].cap,res));
 38             res-=tp;
 39             edge[i].cap-=tp;
 40             edge[i^1].cap+=tp;
 41             if(!res||h[S]==n)
 42                 return flow-res;
 43         }
 44         if(edge[i].cap>0&&h[y]<pos)
 45             pos=h[y];
 46     }
 47     if(res==flow)
 48     {
 49         num[h[x]]--;
 50         if(num[h[x]]==0)
 51         {
 52             h[S]=n;
 53             return flow-res;
 54         }
 55         h[x]=pos+1;
 56         num[h[x]]++;
 57     }
 58     return flow-res;
 59 }
 60 void Sap()
 61 {
 62     memset(h,0,sizeof(h));
 63     memset(num,0,sizeof(num));
 64     int ans=0;
 65     num[0]=n;
 66     while(h[S]!=n)
 67         ans+=findpath(S,inff);
 68 }
 69 bool vis[N];
 70 void dfs(int now)
 71 {
 72     vis[now]=true;
 73     for(int i=head[now];i!=-1;i=edge[i].next)
 74     {
 75         if(!vis[edge[i].y]&&edge[i].cap)
 76             dfs(edge[i].y);
 77     }
 78 }
 79 bool mark[N];
 80 bool check(int now)
 81 {
 82     mark[now]=true;
 83     if(now==T)
 84         return true;
 85     for(int i=head[now];i!=-1;i=edge[i].next)
 86     {
 87         if(!mark[edge[i].y]&&edge[i].cap&&check(edge[i].y))
 88                 return true;
 89     }
 90     return false;
 91 }
 92 int main()
 93 {
 94     int m;
 95     while(scanf("%d%d",&n,&m)!=EOF)
 96     {
 97         nc=0;
 98         memset(head,-1,sizeof(head));
 99         for(int i=0; i<m; i++)
100         {
101             int a,b,c;
102             scanf("%d%d%d",&a,&b,&c);
103             add(a,b,c);
104         }
105         S=0,T=n-1;
106         Sap();
107         memset(vis,false,sizeof(vis));
108         dfs(S);
109         int cnt=0;
110         for(int i=0;i<n;i++)
111         {
112             if(!vis[i])
113                 continue;
114             for(int j=head[i];j!=-1;j=edge[j].next)
115             {
116                 if(j&1)
117                     continue;
118                 int t=edge[j].y;
119                 if(!vis[t])
120                 {
121                     memset(mark,false,sizeof(mark));
122                     if(check(t))
123                         cnt++;
124                 }
125             }
126         }
127         printf("%d\n",cnt);
128     }
129     return 0;
130 }