這題還是有點技巧的。
我們求出了最大流,怎樣知道哪些邊可以使得流量增大呢?
若存在e(U,V):S->U路徑上的點都有剩餘容量,V->T路徑上的點都有剩餘容量。
如果有某條邊為上述情況,那麼對邊e進行擴容,最大流增大。
應該十分好理解吧。通過源點進行DFS尋找S集合中所有的點進行標號,很容易。
那麼...V到T可達這怎麼弄呢?
同樣我們通過T來DFS只要存在點V到T有剩餘容量,則V為集合T的點,在DFS(V);
由夠邊的特殊性,我們可以發現,當前邊k的反向邊就是k^1,通過k^1來判斷有剩餘容量就行了。
這樣標號為2.
最後掃一遍邊,串連兩個集合的邊為可擴容邊。
PS:不要把反向邊包含進去了....
#include<iostream>#include<cstdio>#define MN 1111#define MM 22222#define CC(a) memset(a,0,sizeof(a))#define FF(i,m) for( int i=0;i<m;i++ )#define INF 0x0FFFFFFFtemplate<class T>inline void checkmin( T &a,T b ){ if( a>b||a==-1 ) a=b; }using namespace std;struct edge{ int u,pos,c,f,next;}E[MM];int N,M,s,t,alloc;int head[MN],gap[MN],dis[MN],cur[MN],pre[MN];void addEdge( int u,int v,int c,int cc=0 ){ E[alloc].u=u; E[alloc].pos=v; E[alloc].c=c; E[alloc].next=head[u]; head[u]=alloc++; E[alloc].u=v; E[alloc].pos=u; E[alloc].c=cc; E[alloc].next=head[v]; head[v]=alloc++;}void setG(){ CC(E);alloc=0; s=0;t=N-1; memset( head,-1,sizeof(head) ); int u,v,c; while( M-- ){ scanf("%d%d%d",&u,&v,&c); addEdge( u,v,c ); }}int sap(){ CC(dis),CC(gap); FF(i,t+1) cur[i]=head[i]; int u=pre[s]=s,maxflow=0,aug=-1; gap[0]=t+1; while( dis[s]<=t ){loop: for( int &i=cur[u];i!=-1;i=E[i].next ) { int v=E[i].pos; if( E[i].c-E[i].f && dis[u]==dis[v]+1 ) { pre[v]=u; checkmin(aug,E[i].c-E[i].f); u=v; if( v==t ) { maxflow+=aug; for( u=pre[u];v!=s;v=u,u=pre[u] ) E[cur[u]].f+=aug,E[cur[u]^1].f-=aug; aug=-1; } goto loop;} } int mind=t; for( int i=head[u];i!=-1;i=E[i].next ) { int v=E[i].pos; if( E[i].c-E[i].f && mind>dis[v] ) cur[u]=i,mind=dis[v]; } if( --gap[dis[u]]==0 )break; gap[dis[u]=mind+1]++; u=pre[u]; } return maxflow;}int flag[MN];void dfss( int cur ){ flag[cur]=1; for( int v=head[cur];v!=-1;v=E[v].next ) if( !flag[E[v].pos]&&(E[v].c-E[v].f) ) dfss(E[v].pos);}void dfst( int cur ){ flag[cur]=2; for( int v=head[cur];v!=-1;v=E[v].next ) if( !flag[E[v].pos]&&(E[v^1].c-E[v^1].f) ) dfst(E[v].pos);}int main(){ while( scanf("%d%d",&N,&M)!=EOF ) { setG(); int ans=0; int maxflow=sap(); //printf( "%d\n",maxflow ); CC(flag); dfss(s);dfst(t); for( int i=0;i<alloc;i+=2 ) if( flag[E[i].u]==1&&flag[E[i].pos]==2&&E[i].c==E[i].f ) ans++; printf( "%d\n",ans ); } return 0;}/*4 60 1 40 2 21 2 21 3 12 3 72 0 1ans:3*/