POJ 3204 求使得最大流增大的边

来源:互联网 发布:淘宝网魔豆妈妈店铺 编辑:程序博客网 时间:2024/06/08 08:22

这题还是有点技巧的。

我们求出了最大流,怎样知道哪些边可以使得流量增大呢?


若存在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*/


原创粉丝点击