题目链接: 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在老博客里说他的超时了。
代码:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
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 }