hdu4940,sgu194,无源汇上下界网络流
来源:互联网 发布:c#获取网页源码 编辑:程序博客网 时间:2024/04/30 01:07
曾几何时我做了一个有源汇的上下界网络流问题。
真是复杂到蛋疼,本来就有源汇,还非要把源和汇连起来,再新建一个超级源和超级汇。
我还隐约记得,说这样的问题要转化为无源汇的网络流来做。当时根本没理会这句话的含义。
当时就没仔细思考。。然后看到这个无源汇的题,就果断呵呵了。
学习上下界网络流请见周源2004论文《一种简易的方法求解流量有上下界的网络中网络流问题》。很巧妙,无源汇的一种可行流刚好可以对应新建图的一种流。
记录一下建图方式:low是流量下界,up是上界。
新建一个源s,汇t
对于两个节点i,j,addedge(i,j,up[i][j]-low[i][j]);
对于某个节点i,计算tf=sum{low[j][i]-low[i][j]},
如果tf大于0,即某个节点的下界流入量大于流出量,addedge(s,i,tf);
如果tf小于0,addedge(i,t,-tf);
如果源所有边满流,那么存在可行流,否则不存在。
这种问题还可以拓展,例如:
1.上面所说的有源汇的上下界。转化为无源汇来做。即建一条原汇点到原源点的上界为inf,下界为0的边。
2.有源汇的最小流,同上,二分上界。
hdu4940。这题有点惨。官方题解证明似乎有点诡异,我看了半天才稍微理解。
这种题真是我的弱项,用图论或其它算法来表示数学关系。
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define INF 1000000000#define Maxn 220#define Maxm 50100struct edge{int u,v,c;}ed[Maxm];//Maxm要为连接关系数量的两倍int fi[Maxn],ne[Maxm],te,lev[Maxn];int pe[Maxn],cap[Maxn],tc[Maxn],sta[Maxn];void init(){ memset(fi,-1,sizeof(fi)); te=0;}void insert(int u,int v,int c){ ed[te].u=u;ed[te].v=v;ed[te].c=c; ne[te]=fi[u];fi[u]=te++; ed[te].u=v;ed[te].v=u;ed[te].c=0; ne[te]=fi[v];fi[v]=te++;}int dinic_bfs(int s,int t){ memset(lev,0,sizeof(lev)); lev[s]=1; queue<int> q; q.push(s); int u,v,e,c; while(!q.empty()){ u=q.front();q.pop(); for(e=fi[u];e!=-1;e=ne[e]){ v=ed[e].v;c=ed[e].c; if (!lev[v]&&c){ lev[v]=lev[u]+1; q.push(v); } } if (u==t) break; } return lev[t];}int dinic_dfs1(int u,int t,int cap){ int tc=cap; if (u==t) return cap; int v,e,c,tf; for(e=fi[u];e!=-1&&tc;e=ne[e]){ v=ed[e].v; c=ed[e].c; if (lev[v]==lev[u]+1&&c>0){ tf=dinic_dfs1(v,t,min(tc,c)); tc-=tf; ed[e].c-=tf; ed[e^1].c+=tf; } } if (e==-1) lev[u]=-10; return cap-tc;}int dinic_dfs(int s,int t,int tn){//stack int top=0,i,flow=0; sta[++top]=s; cap[s]=tc[s]=INF; pe[s]=fi[s]; int u,v,c,tf; while(top){ u=sta[top]; if (u!=t) for(int &e=pe[u];e!=-1&&tc[u];e=ne[e]){ v=ed[e].v;c=ed[e].c; if (lev[v]==lev[u]+1&&c){ sta[++top]=v;pe[v]=fi[v];tc[v]=cap[v]=min(c,tc[u]); break; } } else tc[u]=0; if (tc[u]==0||pe[u]==-1) { tf=cap[u]-tc[u]; if (pe[u]==-1) lev[u]=-10; top--; if (top){ tc[sta[top]]-=tf; ed[pe[sta[top]]].c-=tf; ed[pe[sta[top]]^1].c+=tf; pe[sta[top]]=ne[pe[sta[top]]]; } else flow+=tf; } } return flow;}int dinic(int s,int t,int tn){//起点终点相等需要特判 int flow=0; int tf=0; while(dinic_bfs(s,t)){ flow+=dinic_dfs(s,t,t+1); } return flow;}int b[Maxn][Maxn],d[Maxn][Maxn];int main(){ int tcas,cas,n,m,i,j,x,y,dd,bb,s,t,sum,tsum,tf; scanf("%d",&tcas); for(cas=1;cas<=tcas;++cas){ scanf("%d%d",&n,&m); init(); memset(b,-1,sizeof(b)); for(i=1;i<=m;++i){ scanf("%d%d%d%d",&x,&y,&dd,&bb); b[x][y]=bb; d[x][y]=dd; } s=0;t=n+1; for(i=1;i<=n;++i){ for(j=1;j<=n;++j)if (b[i][j]!=-1){ insert(i,j,b[i][j]); } } tsum=0; for(i=1;i<=n;++i){ tf=0; for(j=1;j<=n;++j){ if (b[j][i]!=-1) tf+=d[j][i]; if (b[i][j]!=-1) tf-=d[i][j]; } if (tf<0) {insert(i,t,-tf);tsum-=tf;} else if (tf>0) insert(s,i,tf); } //printf("tsum:%d\n",tsum); sum=dinic(s,t,t+1); printf("Case #%d: ",cas); if (sum==tsum){ printf("happy\n"); } else printf("unhappy\n"); } return 0;}
不过,听说很多人都是水过的……
枚举一个点为S集合,或者为T都能AC。。那个证明并不完善吧?
#include<iostream>#include<cstdio>#include<cstring>using namespace std;#define Maxn 210int b[Maxn][Maxn],d[Maxn][Maxn];int main(){ int tcas,cas,n,m,x,y,c,f,fl,i,j; scanf("%d",&tcas); for(cas=1;cas<=tcas;++cas){ scanf("%d%d",&n,&m); memset(d,0,sizeof(d)); memset(b,0,sizeof(b)); for(i=1;i<=m;++i){ scanf("%d%d%d%d",&x,&y,&c,&f); d[x][y]=c; b[x][y]=f; } fl=0; for(i=1;i<=n;++i){ x=0; y=0; for(j=1;j<=n;++j)if (j!=i){ //x+=d[i][j]; //枚举i作为S集合 //y+=d[j][i]+b[j][i]; x+=d[j][i]; //枚举i作为T集合 y+=d[i][j]+b[i][j]; } if (x>y) {fl=1;break;} } printf("Case #%d: ",cas); if (fl==0) printf("happy\n"); else printf("unhappy\n"); } return 0;}
另外,来个练习题。SGU194。
输出的时候脑残把剩余流量当成流量,调了半天……
#include<iostream>#include<cstdio>#include<cstring>#include<queue>using namespace std;#define INF 1000000000#define Maxn 220#define Maxm 50100struct edge{int u,v,c;}ed[Maxm];int fi[Maxn],ne[Maxm],te,lev[Maxn];int pe[Maxn],cap[Maxn],tc[Maxn],sta[Maxn];void init(){ memset(fi,-1,sizeof(fi)); te=0;}void insert(int u,int v,int c){ ed[te].u=u;ed[te].v=v;ed[te].c=c; ne[te]=fi[u];fi[u]=te++; ed[te].u=v;ed[te].v=u;ed[te].c=0; ne[te]=fi[v];fi[v]=te++;}int dinic_bfs(int s,int t){ memset(lev,0,sizeof(lev)); lev[s]=1; queue<int> q; q.push(s); int u,v,e,c; while(!q.empty()){ u=q.front();q.pop(); for(e=fi[u];e!=-1;e=ne[e]){ v=ed[e].v;c=ed[e].c; if (!lev[v]&&c){ lev[v]=lev[u]+1; q.push(v); } } if (u==t) break; } return lev[t];}int dinic_dfs1(int u,int t,int cap){ int tc=cap; if (u==t) return cap; int v,e,c,tf; for(e=fi[u];e!=-1&&tc;e=ne[e]){ v=ed[e].v; c=ed[e].c; if (lev[v]==lev[u]+1&&c>0){ tf=dinic_dfs1(v,t,min(tc,c)); tc-=tf; ed[e].c-=tf; ed[e^1].c+=tf; } } if (e==-1) lev[u]=-10; return cap-tc;}int dinic(int s,int t,int tn){ int flow=0; int tf=0; while(dinic_bfs(s,t)){ flow+=dinic_dfs1(s,t,t+1); } return flow;}int low[Maxn][Maxn],up[Maxn][Maxn];int lm[Maxm];int main(){ int n,m,i,j,x,y,ll,uu,s,t,sum,tsum,tf; while(scanf("%d%d",&n,&m)!=EOF){ init(); s=n+1;t=n+2; memset(low,-1,sizeof(low)); for(i=1;i<=m;++i){ scanf("%d%d%d%d",&x,&y,&ll,&uu); low[x][y]=ll; up[x][y]=uu; insert(x,y,uu-ll); lm[i]=ll; } tsum=0; for(i=1;i<=n;++i){ tf=0; for(j=1;j<=n;++j){ if (low[j][i]!=-1) tf+=low[j][i]; if (low[i][j]!=-1) tf-=low[i][j]; } if (tf<0) {insert(i,t,-tf);tsum-=tf;} else if (tf>0) insert(s,i,tf); } sum=dinic(s,t,t+1); if (sum==tsum){ printf("YES\n"); for(i=0;i<m;i++){ printf("%d\n",ed[i*2+1].c+lm[i+1]); } } else printf("NO\n"); } return 0;}
0 0
- hdu4940,sgu194,无源汇上下界网络流
- SGU194 无源汇上下界可行流 上下界网络流 pascal
- sgu194 无源汇带有下界的网络流
- sgu194 无源汇上下界的最大流
- 【SGU194】Reactor Cooling 无源汇上下界可行流
- sgu194. Reactor Cooling 无源汇上下界可行流
- hdu4940 有上下界的无源可行流判断
- [ZOJ2314]/[SGU194] Reactor Cooling 无源汇有上下界网络流
- 无源汇上下界网络流 zju zoj 2314
- ZOJ 2314 Reactor Cooling 无源汇上下界网络流
- 【无源汇的上下界网络流】【模板】
- ACdream 1211 (无源汇上下界网络流)
- 【上下界网络流】sgu194 zoj3229 sgu176 zoj1994 zoj3496
- 【上下界网络流】sgu194 zoj3229 sgu176 zoj1994 zoj3496
- sgu194:Reactor Colling(无源无汇上下界最大流)
- 【无源汇点上下界可行流】[SGU194]Reactor Cooling
- 无源汇上下界可行流模版
- ZOJ 2314 Reactor Cooling 上下界网络流(无源汇可行流)
- 设置linux路径显示
- 【Twitter Storm系列】Storm环境配置及吞吐量测试调优--个人理解
- oracle的trunc用法
- MongoDB 入门
- Linux设备驱动之Ioctl控制
- hdu4940,sgu194,无源汇上下界网络流
- 3D打印机开源、免费分层软件介绍
- Memcached_Session_Manager介绍及使用
- 【动态规划】【2014 Multi-University Training Contest 4】The Romantic Hero
- listview的滑动删除
- Java中getResourceAsStream的用法
- cocos2dx fnt字体、自定义字体制作(转载、记录、待验证)
- matlab GUI界面实现单选按钮(radiobutton)
- spring security 示例