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*/
- POJ 3204 求使得最大流增大的边
- Uva 11248 求只修改一条边的流量使得最大流>c 的所有可行边
- POJ 2253 floyd求最大边的最小值
- 增大Linux的socket最大连接数
- 增大Linux的socket最大连接数
- 增大apache 2的最大连接数
- 增大Linux的socket最大连接数
- poj 3525 求凸多边形的最大内切圆
- HDU 4289 最小割=最大流 求去掉最少点权值使得 起末点不连通
- POJ 2987 Firing---dinic求最大流
- 【玲珑杯 1047】【二分匹配 KM算法或者费用流】Best couple【定义男女生的距离为最短距离,求匹配之后使得总距离最大】
- poj 3522(求最小生成树,使得最边和最小边差最小)
- 增大虚拟机最大硬盘空间~
- 求整形数组的一个子数组,使得该子数组所有元素的和的绝对值最大。
- 求不降序的数组arr中最大索引i使得arr[i]小于给定关键字,不存在则返回-1
- windows XP 增大 IIS的最大连接数
- POJ 3204 最大流
- poj 3204 最大流
- Virtual Box 虚拟机和主机之间进行通信的设置方法
- Spring inject Date into bean property – CustomDateEditor
- Android上传文件至服务器
- DDK(Driver Developer Kit)和WDK(Windows Driver Kit)的区别
- c库函数参考手册
- POJ 3204 求使得最大流增大的边
- 把一个逗号分开的字符串转化为数组的两个方法
- 实用的20条编程经验
- layoutSubviews 用法
- android Button事件处理
- android输入子系统模型分析:
- OpenWRT移植到三星S5PV210处理器上
- CSS分割图片
- Toll-Free Bridging