您的位置:首页 > Web前端 > React

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

2016-03-26 01:00 555 查看
[b]题目链接:[/b]

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

[b]题目大意:[/b]

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

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

[b]题目思路:[/b]

  【无源汇上下界最大流】

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

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

  建图模型:(学习自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的出边都满流时),有可行解。

  

//
//by coolxxx
//
#include<iostream>
#include<algorithm>
#include<string>
#include<iomanip>
#include<memory.h>
#include<time.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<stdbool.h>
#include<math.h>
#define min(a,b) ((a)<(b)?(a):(b))
#define max(a,b) ((a)>(b)?(a):(b))
#define abs(a) ((a)>0?(a):(-(a)))
#define lowbit(a) (a&(-a))
#define sqr(a) (a)*(a)
#define swap(a,b) (a)^=(b),(b)^=(a),(a)^=(b)
#define eps 1e-8
#define MAX 0x7f7f7f7f
#define PI 3.1415926535897
#define N 20004
#define M 1000004
using namespace std;
int n,m,cas,lll,ans;
int S,T,nn;
int last
,in
,d
,vd
,low
;
char s
;
bool inq
;
struct xxx
{
int next,to,f;
}e[M];
void add(int x,int y,int f)
{
e[++lll].next=last[x];
last[x]=lll;
e[lll].to=y;
e[lll].f=f;
}
void link(int x,int y,int f)
{
add(x,y,f);
add(y,x,0);
}
void build()
{
int i,f,x,y,b,c;
lll=1;ans=0;
memset(low,0,sizeof(low));
memset(in,0,sizeof(in));
memset(last,0,sizeof(last));
memset(e,0,sizeof(e));
memset(d,0,sizeof(d));
memset(vd,0,sizeof(vd));
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d%d%d%d",&x,&y,&b,&c);
in[x]-=b;in[y]+=b;
link(x,y,c-b);
low[i]=b;
}
S=n+1;
T=n+2;
nn=n+2;
for(i=1;i<=n;i++)
{
if(in[i]>0)link(S,i,in[i]);
if(in[i]<0)link(i,T,-in[i]);
}
}
int sap(int u,int f)
{
int i,tt,asp=0,mix=nn-1;
if(u==T)return f;
for(i=last[u];i;i=e[i].next)
{
if(e[i].f>0)
{
if(d[u]==d[e[i].to]+1)
{
tt=sap(e[i].to,min(f-asp,e[i].f));
asp+=tt;
e[i].f-=tt;
e[i^1].f+=tt;
if(asp==f || d[S]==nn)
return asp;
}
mix=min(mix,d[e[i].to]);
}
}
if(asp!=0)return asp;
if(!--vd[d[u]])d[S]=nn;
else vd[d[u]=mix+1]++;
return asp;
}
int main()
{
#ifndef ONLINE_JUDGE
//    freopen("1.txt","r",stdin);
//    freopen("2.txt","w",stdout);
#endif
int i,j,f;
//    while(~scanf("%s",s))
while(~scanf("%d",&n) && n)
{
build();
vd[0]=nn;
while(d[S]<nn)
{
f=sap(S,MAX);
ans+=f;
}
for(i=last[S],f=1;i;i=e[i].next)
{
if(e[i].f>0)
{
f=0;
break;
}
}
if(!f)
puts("NO");
else
{
puts("YES");
for(i=1;i<=m;i++)
printf("%d\n",low[i]+e[i+i+1].f);
}
}
return 0;
}

/*
//

//
*/


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: