坐井观天

In the name of dream

导航

sgu 194 无源汇的上下界可行流

Posted on 2012-06-17 14:15  一毛_  阅读(286)  评论(0编辑  收藏  举报

题目链接: http://acm.sgu.ru/problem.php?contest=0&problem=194

题目大意:

  给定一个n个点,m条边的网络,每条边允许的流量范围< lij, cij >,问是否存在一个可行流可以在该网络内循环流动。

 

分析:

  这是我做的第一个有上下界的可行流,这里的可行流应该指满足三个条件:

  1、流量平衡条件,2、容量限制条件即 lij <= fij <= cij; 3、反对称性: fij = -fji;

  思路是添加附加源和附件汇,一条边拆成三条边来构图达到容量限制的条件然后跑一遍最大流,参考自04年周源的国家集训队作业《一种简易的方法求解流量有上下界的网络中网络流问题》。

  代码我参考了: http://txhwind.diandian.com/post/2012-03-14/19643163

  最后还是证明EK模版是可以跑200个点的(事实上本来就可以),虽然DD在老博客里说他的超时了。

 

代码:

sgu194
  1 /*17.06.12 10:08    yimao     194    .CPP    Accepted    296 ms    1803 kb*/
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <iostream>
  6 #include <algorithm>
  7 #include <vector>
  8 using namespace std;
  9 
 10 #define mpair make_pair
 11 #define pii pair<int,int>
 12 #define MM(a,b) memset(a,b,sizeof(a));
 13 typedef long long lld;
 14 typedef unsigned long long u64;
 15 template<class T> bool up_max(T& a,const T& b){return b>a? a=b,1 : 0;}
 16 template<class T> bool up_min(T& a,const T& b){return b<a? a=b,1 : 0;}
 17 #define maxn 210
 18 const int inf= 2100000000;
 19 
 20 int n,m;
 21 int ST, ED;
 22 int g[maxn][maxn];
 23 pii e[maxn*maxn];
 24 int l[maxn][maxn], c[maxn][maxn];
 25 
 26 bool vis[maxn];
 27 int pre[maxn], que[maxn];
 28 bool bfs(){
 29     fill( vis, vis+2+n, 0 );
 30     int head= 0, tail= 0;
 31     que[tail++]= ST;
 32     vis[0]= ST;
 33     while( head<tail ){
 34         int u= que[head++];
 35         for(int v=1;v<=ED;++v){ /// ST==0;
 36             if( g[u][v]>0 && !vis[v] ){
 37                 pre[v]= u;
 38                 if( v==ED ) return 1;
 39                 que[tail++]= v;
 40                 vis[v]= 1;
 41             }
 42         }
 43     }
 44     return 0;
 45 }
 46 
 47 int Edmond_karp(){
 48     int ret= 0;
 49     ST= 0, ED= n+1;
 50     while( bfs() ){
 51         int t= inf;
 52         for(int i=ED;i!=ST;i=pre[i])
 53             up_min( t, g[pre[i]][i] );
 54         ret+= t;
 55         for(int i=ED;i!=ST;i=pre[i]){
 56             g[pre[i]][i]-= t;
 57             g[i][pre[i]]+= t;
 58         }
 59     }
 60     return ret;
 61 }
 62 
 63 int main()
 64 {
 65    //freopen("sgu194.in","r",stdin);
 66     while( cin>>n>>m ){
 67         for(int i=1;i<=n;++i)for(int j=1;j<=n;++j)l[i][j]= c[i][j]= 0;
 68         for(int i=0;i<=n+1;++i)for(int j=0;j<=n+1;++j)g[i][j]= 0;
 69 
 70         for(int i=1;i<=m;++i){
 71             int u,v,l1,l2;
 72             scanf("%d%d%d%d", &u, &v, &l1, &l2);
 73             e[i]= pii( u, v );
 74             l[u][v]= l1, c[u][v]= l2;
 75         }
 76 
 77         int sum= 0;
 78         for(int i=1;i<=n;++i){
 79             int t= 0;
 80             for(int j=1;j<=n;++j){
 81                 t+= l[j][i]-l[i][j];
 82                 g[i][j]= c[i][j]-l[i][j];
 83 
 84             }
 85             if( t>0 )
 86                 sum+= g[0][i]=t;
 87             else g[i][n+1]= -t;
 88         }
 89 
 90         int ret= Edmond_karp();
 91         if( ret<sum ) puts("NO");
 92         else{
 93             puts("YES");
 94             for(int i=1;i<=m;++i){
 95                 int x= e[i].first, y= e[i].second;
 96                 printf("%d\n", c[x][y]-g[x][y] );
 97             }
 98         }
 99     }
100 }