【无源汇上下界最大流】SGU 194 Reactor Cooling

题目链接:

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

题目大意:

  n个点n<20000!!!不是200!!!RE了无数次,m条边(管子)(m范围好像没说,我开了10^6),每个点流入的和流出的液体要相等,每条边(管子)有上下界流量,问是否有解,有解YES无解NO,有解还要输出每条边的流量。

  题目输入样例略坑,我以为要多组数据输入输出TEST #1 什么的。后来仔细看了Input发现只有一组吧应该,保险起见还是写了多组,但是不用读入TEST是肯定的。

题目思路:

  【无源汇上下界最大流】

  直接建图套最大流模版即可。

  最近刚好在搞上下界问题,等到都做完了写个总结吧。

  建图模型:(学习自Mr. Ant http://www.cnblogs.com/kane0526/archive/2013/04/05/3001108.html

  以前写最大流默认下界为0,而这里的下界却不为0,所以我们要进行再构造让每条边的下界为0,这样做是为了方便处理。

  对于每条边(管子)有一个上界容量c和一个下界容量b,我们让这条边(管子)的容量下界变为0,上界为b-c。

  可是这样做的话流量就不守恒了,为了再次满足流量守恒,增设一个超级源点S和一个超级终点T。

  我们开设一个数组in[]来记录每个节点的流量情况。

  in[i]=Σi入下界i出下界(i节点所有入流下界之和-i节点所有出流下界之和)。

  当in[i]大于0的时候,S到i连一条流量为in[i]的边。

  当in[i]小于0的时候,i到T连一条流量为-in[i]的边。

  最后对(S,T)求一次最大流即可,当所有附加边全部满流时(S的出边都满流时),有可行解。

  

  1 //
  2 //by coolxxx
  3 //
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<string>
  7 #include<iomanip>
  8 #include<memory.h>
  9 #include<time.h>
 10 #include<stdio.h>
 11 #include<stdlib.h>
 12 #include<string.h>
 13 #include<stdbool.h>
 14 #include<math.h>
 15 #define min(a,b) ((a)<(b)?(a):(b))
 16 #define max(a,b) ((a)>(b)?(a):(b))
 17 #define abs(a) ((a)>0?(a):(-(a)))
 18 #define lowbit(a) (a&(-a))
 19 #define sqr(a) (a)*(a)
 20 #define swap(a,b) (a)^=(b),(b)^=(a),(a)^=(b)
 21 #define eps 1e-8
 22 #define MAX 0x7f7f7f7f
 23 #define PI 3.1415926535897
 24 #define N 20004
 25 #define M 1000004
 26 using namespace std;
 27 int n,m,cas,lll,ans;
 28 int S,T,nn;
 29 int last[N],in[N],d[N],vd[N],low[N];
 30 char s[N];
 31 bool inq[N];
 32 struct xxx
 33 {
 34     int next,to,f;
 35 }e[M];
 36 void add(int x,int y,int f)
 37 {
 38     e[++lll].next=last[x];
 39     last[x]=lll;
 40     e[lll].to=y;
 41     e[lll].f=f;
 42 }
 43 void link(int x,int y,int f)
 44 {
 45     add(x,y,f);
 46     add(y,x,0);
 47 }
 48 void build()
 49 {
 50     int i,f,x,y,b,c;
 51     lll=1;ans=0;
 52     memset(low,0,sizeof(low));
 53     memset(in,0,sizeof(in));
 54     memset(last,0,sizeof(last));
 55     memset(e,0,sizeof(e));
 56     memset(d,0,sizeof(d));
 57     memset(vd,0,sizeof(vd));
 58     scanf("%d",&m);
 59     for(i=1;i<=m;i++)
 60     {
 61         scanf("%d%d%d%d",&x,&y,&b,&c);
 62         in[x]-=b;in[y]+=b;
 63         link(x,y,c-b);
 64         low[i]=b;
 65     }
 66     S=n+1;
 67     T=n+2;
 68     nn=n+2;
 69     for(i=1;i<=n;i++)
 70     {
 71         if(in[i]>0)link(S,i,in[i]);
 72         if(in[i]<0)link(i,T,-in[i]);
 73     }
 74 }
 75 int sap(int u,int f)
 76 {
 77     int i,tt,asp=0,mix=nn-1;
 78     if(u==T)return f;
 79     for(i=last[u];i;i=e[i].next)
 80     {
 81         if(e[i].f>0)
 82         {
 83             if(d[u]==d[e[i].to]+1)
 84             {
 85                 tt=sap(e[i].to,min(f-asp,e[i].f));
 86                 asp+=tt;
 87                 e[i].f-=tt;
 88                 e[i^1].f+=tt;
 89                 if(asp==f || d[S]==nn)
 90                     return asp;
 91             }
 92             mix=min(mix,d[e[i].to]);
 93         }
 94     }
 95     if(asp!=0)return asp;
 96     if(!--vd[d[u]])d[S]=nn;
 97     else vd[d[u]=mix+1]++;
 98     return asp;
 99 }
100 int main()
101 {
102     #ifndef ONLINE_JUDGE
103 //    freopen("1.txt","r",stdin);
104 //    freopen("2.txt","w",stdout);
105     #endif
106     int i,j,f;
107 //    while(~scanf("%s",s))
108     while(~scanf("%d",&n) && n)
109     {
110         build();
111         vd[0]=nn;
112         while(d[S]<nn)
113         {
114             f=sap(S,MAX);
115             ans+=f;
116         }
117         for(i=last[S],f=1;i;i=e[i].next)
118         {
119             if(e[i].f>0)
120             {
121                 f=0;
122                 break;
123             }
124         }
125         if(!f)
126             puts("NO");
127         else
128         {
129             puts("YES");
130             for(i=1;i<=m;i++)
131                 printf("%d\n",low[i]+e[i+i+1].f);
132         }
133     }
134     return 0;
135 }
136 
137 
138 /*
139 //
140 
141 //
142 */
View Code

 

posted @ 2016-03-26 01:00  Cool639zhu  阅读(261)  评论(0编辑  收藏  举报