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

ZOJ 2314 Reactor Cooling

2016-12-28 18:57 337 查看
题意:

n个点,m条水管,每条水管规定要从i到j有[L,R]的流量,

每个点流入流量和流出流量必须相等,构造出一种复合题意的解,或者证明无解



solution:

就是构造无源汇可行流啦,,建模方法如下

对每条[L,R]的边,从i到j连一条容量为R - L的边,对于每个点,

统计流入它的所有管道的下界流量和in[i],

类似地统计从它流出的下界流量和out[i],

定义du[i] = in[i] - out[i],

若du[i] > 0,说明该点要额外流出du[i]的流量,那么从S到i连一条容量为du[i]的边,

否则从i到T连一条容量为-du[i]的边

原图有可行流,当且仅当所有附加边满载(就是连接S,T的边),直接输出即可

#include<iostream>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#include<cmath>
#include<cstdio>
#include<bitset>
using namespace std;

const int maxn = 233;
const int maxm = 2E5 + 20;
const int INF = ~0U>>1;

struct E{
int to,cap,flow,Num; E(){}
E(int to,int cap,int flow,int Num):
to(to),cap(cap),flow(flow),Num(Num){}
}edgs[maxm];

int n,S,T,m,cnt,tot,Ans[maxm],in[maxn],out[maxn],cur[maxn],L[maxn];

vector <int> v[maxn];
queue <int> Q;

void Add(int x,int y,int cap,int Num)
{
v[x].push_back(cnt); edgs[cnt++] = E(y,cap,0,Num);
v[y].push_back(cnt); edgs[cnt++] = E(x,0,0,0);
}

int Dinic(int x,int a)
{
if (x == T) return a; int flow = 0;
for (int &i = cur[x]; i < v[x].size(); i++)
{
E &e = edgs[v[x][i]];
if (e.cap == e.flow || L[e.to] != L[x] + 1) continue;
int f = Dinic(e.to,min(a,e.cap - e.flow));
if (!f) continue; flow += f; e.flow += f;
edgs[v[x][i]^1].flow -= f; a -= f;
if (!a) return flow;
}
if (!flow) L[x] = -1;
return flow;
}

bool BFS()
{
for (int i = S; i <= T; i++) L[i] = 0;
L[S] = 1; Q.push(S);
while (!Q.empty())
{
int k = Q.front(); Q.pop();
for (int i = 0; i < v[k].size(); i++)
{
E e = edgs[v[k][i]];
if (e.cap == e.flow || L[e.to]) continue;
L[e.to] = L[k] + 1; Q.push(e.to);
}
}
return L[T];
}

int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif

int cas; cin >> cas;
while (cas--)
{
scanf("%d%d",&n,&m); T = n + 1; cnt = tot = 0;
for (int i = 0; i <= n; i++)
v[i].clear(),in[i] = out[i] = 0;
for (int i = 1; i <= m; i++)
{
int x,y,l,c;
scanf("%d%d%d%d",&x,&y,&l,&c);
Add(x,y,c - l,i); Ans[i] = l;
in[y] += l; out[x] += l;
}
for (int i = 1; i <= n; i++)
{
int du = in[i] - out[i];
if (du > 0) Add(S,i,du,0),tot += du;
else if (du < 0) Add(i,T,-du,0);
}

int MaxFlow = 0;
while (BFS())
{
for (int i = S; i <= T; i++) cur[i] = 0;
MaxFlow += Dinic(S,INF);
}
if (MaxFlow < tot) puts("NO");
else
{
puts("YES");
for (int i = 0; i < cnt; i++)
if (edgs[i].Num) Ans[edgs[i].Num] += edgs[i].flow;
for (int i = 1; i <= m; i++)
printf("%d\n",Ans[i]);
}
puts("");
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: