SGU176 Flow construction
2016-06-27 20:21
323 查看
http://acm.sgu.ru/problem.php?contest=0&problem=176
有源汇上下界最小流,可以选择跟有源汇上下界最大流一样的建图方式,然后用二分去二分t->s这条边的流量,最小的可行流就是答案。
也可以这样:
跟无源汇最大流建图一样,然后不添加t->s的边
对ss->tt求最大流,然后添加t->s的边,求ss->tt最大流,若是满流,则t->s的流量就是最小流
PS:记录一下:SGU的ID是068720
第二种建图方式:
有源汇上下界最小流,可以选择跟有源汇上下界最大流一样的建图方式,然后用二分去二分t->s这条边的流量,最小的可行流就是答案。
也可以这样:
跟无源汇最大流建图一样,然后不添加t->s的边
对ss->tt求最大流,然后添加t->s的边,求ss->tt最大流,若是满流,则t->s的流量就是最小流
PS:记录一下:SGU的ID是068720
第二种建图方式:
#include<cstdio> #include<cmath> #include<algorithm> #include<cstring> #include<iostream> #define inf 0x7fffffff const int maxn=110; const int maxe=maxn*maxn+10; int tot,go[maxe],first[maxn],next[maxe],flow[maxe]; int op[maxe],id[maxe],n,m,du[maxn],cnt[maxn],dis[maxn]; int dn[maxe]; int read(){ int t=0,f=1;char ch=getchar(); while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} return t*f; } void insert(int x,int y,int z){ tot++; go[tot]=y; next[tot]=first[x]; first[x]=tot; flow[tot]=z; } void add(int x,int y,int z){ insert(x,y,z);op[tot]=tot+1; insert(y,x,0);op[tot]=tot-1; } int dfs(int x,int f,int S,int T,int nodes){ if (x==T) return f; int mn=nodes,sum=0; for (int i=first[x];i;i=next[i]){ int pur=go[i]; if (flow[i]&&dis[pur]+1==dis[x]){ int F=std::min(f-sum,flow[i]); int save=dfs(pur,F,S,T,nodes); flow[i]-=save; flow[op[i]]+=save; sum+=save; if (f==sum||dis[S]>=nodes) return sum; } if (flow[i]) mn=std::min(mn,dis[pur]); } if (sum==0){ cnt[dis[x]]--; if (cnt[dis[x]]==0) dis[S]=nodes; else { dis[x]=mn+1; cnt[dis[x]]++; } } return sum; } int mxflow(int S,int T,int nodes){ int res=0; for (int i=0;i<=nodes;i++) cnt[i]=dis[i]=0; while (dis[S]<nodes) res+=dfs(S,inf,S,T,nodes); return res; } int main(){ int s,t; n=read();m=read(); s=0;t=n+1; for (int i=1;i<=m;i++){ int u=read(),v=read(),c=read(),pd=read(); if (pd){ du[u]-=c; du[v]+=c; add(u,v,0); dn[i]=c;id[i]=tot; }else{ add(u,v,c); dn[i]=0;id[i]=tot; } } int sum=0; for (int i=1;i<=n;i++) if (du[i]<0) add(i,t,-du[i]); else add(s,i,du[i]),sum+=du[i]; int sum1=mxflow(s,t,t+1); add(n,1,inf); int sum2=mxflow(s,t,t+1); int sx=0; for (int i=first[s];i;i=next[i]){ if (flow[i]){ puts("Impossible"); return 0; } } printf("%d\n",flow[tot]); for (int i=1;i<=m;i++) printf("%d ",flow[id[i]]+dn[i]); return 0; }
相关文章推荐
- 20150507结构体
- dojo中的this.own()
- for 循环嵌套for循环
- LuManager 2.0.97 设置shopex 手机版waptouch,绑定二级目录
- iOS控件之UIPageControl
- 网络基础知识(1)
- spring mvc @InitBinder
- Android文件读取简单操作
- paramiko模块使用
- CentOS笔记:svn命令行使用说明
- 12_Endnote
- 使用图片来创建动画
- 浅谈Android中的线程
- 11_Emotional factors
- 插入排序法
- 毕设系列-总结(金药食-ToEat)
- Android Service与Activity之间通信的几种方式
- 10_Research_methodology
- duilib + cef简单浏览器的demo2--c++和js交互
- 文件读取