【sgu194】 无源无汇有容量上下界的可行流

题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20757

 

题目大意:给出一个屋源无汇的网络,每条边都有容量上下界,让你求一个可行方案使得每个节点都流量守恒。

 

解题思路:题目既然无源无汇点,那么所有节点都应该满足”入流=出流“这个流量平衡条件,为了方便解题,我们令每条边的容量下界为0,此刻容量上界变成了up-down(上界减去下届),我们定义一个du[]数组保存每个节点的入流之和与出流之和的差,建一个超级源点和一个超级汇点,当du[i]>0,说明入流大于出流,为了满足流量守恒,连一条st到i容量为du[i]的边,当du[i]<0,说明出流大于入流,连一条i到sd容量为-du[i]的边。 

    最构造的网络进行一次最大流,当且仅当所有附加弧满载时原网络有可行流,否则没有。

 

View Code
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <algorithm>
  5 #include <cstring>
  6 using namespace std;
  7 
  8 const int mn=22222;
  9 const int mm=1000000;
 10 const int oo=0x3fffffff;
 11 int node, st, sd, edge, Edge;
 12 int reach[mm], flow[mm], next[mm];
 13 int head[mn], work[mn], dis[mn], que[mn];
 14 int du[mm], ans[mm], id[mm], dn[mm];
 15 
 16 inline void init(int _node, int _st, int _sd)
 17 {
 18     node=_node, st=_st, sd=_sd;
 19     for(int i=0; i<node; i++)
 20         head[i]=-1;
 21     edge=0;
 22 }
 23 
 24 inline void addedge(int u, int v, int c1, int c2, int ID)
 25 {
 26     id[edge]=ID, reach[edge]=v, flow[edge]=c1, next[edge]=head[u],head[u]=edge++;
 27     id[edge]=0, reach[edge]=u, flow[edge]=c2, next[edge]=head[v],head[v]=edge++;
 28 }
 29 
 30 bool bfs()
 31 {
 32     int u, v, l=0, h=0;
 33     for(int i=0; i<node; i++) dis[i]=-1;
 34     que[l++]=st;
 35     dis[st]=0;
 36     while(l!=h)
 37     {
 38         u=que[h++];
 39         if(h==mn) h=0;
 40         for(int i=head[u]; i>=0; i=next[i])
 41         {
 42             v=reach[i];
 43             if(flow[i]&&dis[v]<0)
 44             {
 45                 dis[v]=dis[u]+1;
 46                 que[l++]=v;
 47                 if(l==mn) l=0;
 48                 if(v==sd) return true;
 49             }
 50         }
 51     }
 52     return false;
 53 }
 54 
 55 int dfs(int u, int exp)
 56 {
 57     if(u==sd) return exp;
 58     for(int &i=work[u]; i>=0; i=next[i])
 59     {
 60         int v=reach[i], tp;
 61         if(flow[i]&&dis[v]==dis[u]+1&&(tp=dfs(v,min(flow[i],exp))>0))
 62         {
 63             flow[i]-=tp;
 64             flow[i^1]+=tp;
 65             return tp;
 66         }
 67     }
 68     return 0;
 69 }
 70 
 71 void Dinic()
 72 {
 73     while(bfs())
 74     {
 75         for(int i=0; i<node; i++) work[i]=head[i];
 76         while(dfs(st,oo));
 77     }
 78 }
 79 
 80 int main()
 81 {
 82     int n,m;
 83     while(~scanf("%d%d",&n,&m))
 84     {
 85         init(n+2,0,n+1);
 86         for(int i=1; i<=m; i++)
 87         {
 88             int u, v, down, up;
 89             scanf("%d%d%d%d",&u,&v,&down,&up);
 90             addedge(u,v,up-down,0,i);
 91             du[u]-=down;
 92             du[v]+=down;
 93             dn[i]=down;
 94         }
 95         Edge=edge;
 96         for(int i=1; i<=n; i++)
 97         {
 98             if(du[i]>0) addedge(st,i,du[i],0,0);
 99             if(du[i]<0) addedge(i,sd,-du[i],0,0);
100         }
101         Dinic();
102         bool flag=true;
103         for(int i=head[st]; i>=0; i=next[i])
104             if(flow[i]>0)
105             {
106                 flag=false;
107                 break;
108             }
109         if(!flag) puts("NO");
110         else
111         {
112             puts("YES");
113             for(int i=0; i<Edge; i++) ans[id[i]]=flow[i^1];
114             for(int i=1; i<=m; i++)
115                 printf("%d\n",ans[i]+dn[i]);
116         }
117     }
118     return 0;
119 }

 

转载于:https://www.cnblogs.com/kane0526/archive/2013/03/30/2990184.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值