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