【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 }