Reactor Cooling

sgu194:http://acm.sgu.ru/problem.php?contest=0&problem=194

题意:题目大意:给n个点,及m根pipe,每根pipe用来流躺液体的,单向的,每时每刻每根pipe流进来的物质要等于流出去的物质,要使得m条pipe组成一个循环体,里面流躺物质。并且满足每根pipe一定的流量限制,范围为[Li,Ri].即要满足每时刻流进来的不能超过Ri(最大流问题),同时最小不能低于Li。

题解:题解:。对于每根管子有一个上界容量up和一个下界容量low,我们让这根管子的容量下界变为0,上界为up-low。可是这样做了的话流量就不守恒了,为了再次满足流量守恒,即每个节点"入流=出流”,我们增设一个超级源点st和一个超级终点sd。我们开设一个数组du[]来记录每个节点的流量情况。du[i]=in[i](i节点所有入流下界之和)-out[i](i节点所有出流下界之和)。当du[i]大于0的时候,st到i连一条流量为du[i]的边。当du[i]小于0的时候,i到sd连一条流量为-du[i]的边。最后对(st,sd)求一次最大流即可,如果从源点流出的边都满流了,则就有可行解,否则无解。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<queue>
  4 #include<cstring>
  5 #include<algorithm>
  6 #define min(a,b)(a<b?a:b)
  7 #define INF 1000000
  8 using namespace std;
  9 const int MAX=100010;
 10 struct Node {
 11     int c;
 12     int f;
 13 };
 14 int sx,ex;//sx和ex分别代表源点和汇点
 15 int pre[MAX];
 16 Node map[209][203];
 17 int n,m;
 18 int du[MAX];
 19 int dx[MAX],ll[MAX],rr[MAX];//记录每条边的流量下界,起点,终点
 20 bool BFS() { //BFS搜索层次网络
 21     memset(pre,0,sizeof(pre));
 22     queue< int > Q;
 23     Q.push(sx);
 24     pre[sx]=1;
 25     while(!Q.empty()) {
 26         int d=Q.front();
 27         Q.pop();
 28         for(int i=0; i<=n+1; i++) {
 29             if(!pre[i]&&map[d][i].c-map[d][i].f) {
 30                 pre[i]=pre[d]+1;
 31                 Q.push(i);
 32             }
 33         }
 34     }
 35     return pre[ex]!=0;
 36 }
 37 int dinic(int pos,int flow) { //pos是顶点号,flow是当前顶点所能得到的流量,一次dinic只能求出一次增加的流量,
 38     int f=flow;
 39     if(pos==ex)
 40         return flow;
 41     for(int i=0; i<=1+n; i++) {
 42         if(map[pos][i].c-map[pos][i].f&&pre[pos]+1==pre[i]) {
 43             int a=map[pos][i].c-map[pos][i].f;
 44             int t=dinic(i,min(a,flow));
 45             map[pos][i].f+=t;
 46             map[i][pos].f-=t;
 47             flow-=t;
 48             if(flow<=0)break;
 49             //我最开始就是这里没弄明白,我不明白为什么要此顶点得到的流量减去改变量;
 50             //答案就在下面的  return f-flow;
 51         }
 52     }
 53     if(f-flow<=0)pre[pos]=-1;
 54     return f-flow;//其实这里返回给他前一层的就是这个t;因为t在层函数里面都有,所以所过避免重复就写成这样;
 55 }
 56 void slove(){
 57     int sum=0;
 58     while(BFS()) {
 59         sum+=dinic(sx,INF);
 60     }
 61     //return sum;
 62 }
 63 int main() {
 64     int u,v,t1,t2;
 65     while(cin>>n>>m) {
 66         memset(du,0,sizeof(du));
 67         sx=0;
 68         ex=n+1;
 69         memset(map,0,sizeof(map)) ;
 70         for(int i=1;i<=m; i++) {
 71             cin>>u>>v>>t1>>t2;
 72             map[u][v].c+=t2-t1;
 73             du[u]-=t1;
 74             du[v]+=t1;
 75             dx[i]=t1;
 76             ll[i]=u;
 77             rr[i]=v;
 78         }
 79         for(int i=1;i<=n;i++){
 80            if(du[i]>0)map[0][i].c+=du[i];
 81            if(du[i]<0)map[i][n+1].c+=(-du[i]);
 82         }
 83         slove();
 84         bool flag=false;
 85         for(int i=1;i<=n;i++){
 86             if(du[i]>0){
 87                 if(map[0][i].f!=map[0][i].c){
 88                     flag=true;
 89                     break;
 90                 }
 91 
 92             }
 93         }
 94         if(flag)printf("NO
");
 95         else{
 96           printf("YES
");
 97           for(int i=1;i<=m;i++){
 98               printf("%d
",map[ll[i]][rr[i]].f+dx[i]);
 99           }
100         }
101     }
102     return 0;
103 }
View Code
原文地址:https://www.cnblogs.com/chujian123/p/3947036.html