题目链接:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=11025
题目大意:有一个类似于工业加工生产的机器,起点为1终点为n,中间生产环节有货物加工数量限制,输出u v z c, 当c等于1时表示这个加工的环节必须对纽带上的货物全部加工(即上下界都为z),c等于0表示加工没有上界限制,下界为0,求节点1(起点)最少需要投放多少货物才能传送带正常工作。
解题思路:经典题目,有上下界的最小流。
1、du[i]表示i节点的入流之和与出流之和的差。
2、增设超级源点st和超级汇点sd,连(st,du[i](为正)),(-du[i](为负),sd)。 ///增设超级源点和超级汇点,因为网络中规定不能有弧指向st,也不能有流量流出sd
3、做一次maxflow()。
4、源点(Sd)和起点(St)连一条容量为oo的边。
5、再做一次maxflow()。
6、当且仅当所有附加弧满载时有可行流,最后答案为flow[(Sd-St)^1],St到Sd最大流就是Sd到St最小流。
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=111; 9 const int mm=11111; 10 const int oo=0x3fffffff; 11 int node, st, sd, edge, St, Sd, 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, du[i]=0; 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 int max_flow=0, flow; 74 while(bfs()) 75 { 76 for(int i=0; i<node; i++) work[i]=head[i]; 77 while(flow=dfs(st,oo)) max_flow+=flow; 78 } 79 } 80 81 int main() 82 { 83 int n, m; 84 while(~scanf("%d%d",&n,&m)) 85 { 86 init(n+1,1,n); 87 for(int i=1; i<=m; i++) 88 { 89 int u, v, c, k; 90 scanf("%d%d%d%d",&u,&v,&c,&k); 91 if(k) du[u]-=c, du[v]+=c, ans[i]=c; 92 else addedge(u,v,c,0,i); 93 } 94 St=st, Sd=sd, Edge=edge; 95 st=node, sd=node+1, node+=2; ///增设超级源点和超级汇点,因为网络中规定不能有弧指向st,也不能有流量流出sd 96 head[st]=head[sd]=-1; 97 for(int i=1; i<=n; i++) 98 { 99 if(du[i]>0) addedge(st,i,du[i],0,0); 100 if(du[i]<0) addedge(i,sd,-du[i],0,0); 101 } 102 Dinic(); 103 addedge(Sd,St,oo,0,0); 104 Dinic(); 105 bool flag=true; 106 for(int i=head[st]; i>=0; i=next[i]) 107 if(flow[i]>0) ///当且仅当附加弧达到满负载有可行流 108 { 109 flag=false; 110 break; 111 } 112 if(!flag) 113 puts("Impossible"); 114 else 115 { 116 int res=0, i; 117 for(i=head[Sd]; i>=0; i=next[i]) 118 if(reach[i]==St) break; 119 res=flow[i^1]; 120 printf("%d\n",res); 121 for(i=0; i<Edge; i++) ans[id[i]]=flow[i^1]; 122 for(i=1; i<=m; i++) 123 { 124 if(i!=m) printf("%d ",ans[i]); 125 else printf("%d\n",ans[i]); 126 } 127 } 128 } 129 return 0; 130 }