ZOJ2314 Reactor Cooling
题目大意:给定N(N<=200)个节点和M(范围未知)个管子。每个管子有一个流量的上限和下限(<=100000),求是否能在网络中形成可行流。如果能的话,还要输出每条管子中的流量。
上下界网络流之可行流……这个就是比较基本的模板了。我们统计一下从每个点流入,流出的下限,之后建立辅助原点和辅助汇点,然后对于每个点,用流出下限减去流入下限,如果大于0就向辅助汇点连接容量为差值的边。否则向辅助源点连接容量为差值的绝对值的边。原图中每一条边的容量取上届减去下届的差值。
之后图建好了,直接从辅助源点到辅助汇点跑最大流,判断这个最大流是否与从原点流出的流量相等。如果相等就说明有可行流,否则没有。
这样就结束了,注意在复制head数组的时候不要复制少了。
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<set>
#include<vector>
#include<map>
#include<queue>
#define rep(i,a,n) for(int i = a;i <= n;i++)
#define per(i,n,a) for(int i = n;i >= a;i--)
#define enter putchar('\n')
#define fr friend inline
#define y1 poj
#define mp make_pair
#define pr pair<int,int>
#define fi first
#define sc second
#define pb push_back
using namespace std;
typedef long long ll;
const int M = 100005;
const int N = 205;
const int INF = 1000000009;
const double eps = 1e-7;
int read()
{
int ans = 0,op = 1;char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') op = -1;ch = getchar();}
while(ch >= '0' && ch <= '9') ans = ans * 10 + ch - '0',ch = getchar();
return ans * op;
}
struct edge
{
int next,to,from,v;
}e[M<<1];
int Ti,n,m,head[N<<1],ecnt,x,y,a[M<<1],b[M<<1],rsum[N<<1],csum[N<<1],S,T,tot,dep[N<<1],cur[N<<1];
queue <int> q;
void add(int x,int y,int z)
{
e[++ecnt].to = y;
e[ecnt].next = head[x];
e[ecnt].v = z;
head[x] = ecnt;
}
void clear()
{
memset(head,-1,sizeof(head)),ecnt = -1,tot = 0;
rep(i,S,T) rsum[i] = csum[i] = 0;
}
bool bfs(int s,int t)
{
while(!q.empty()) q.pop();
rep(i,s,t) cur[i] = head[i];
memset(dep,-1,sizeof(dep));
dep[s] = 0,q.push(s);
while(!q.empty())
{
int k = q.front();q.pop();
for(int i = head[k];~i;i = e[i].next)
{
if(e[i].v && dep[e[i].to] == -1)
dep[e[i].to] = dep[k] + 1,q.push(e[i].to);
}
}
return dep[t] != -1;
}
int dfs(int s,int t,int lim)
{
if(s == t || !lim) return lim;
int flow = 0;
for(int i = cur[s];~i;i = e[i].next)
{
cur[s] = i;
if(dep[e[i].to] != dep[s] + 1) continue;
int f = dfs(e[i].to,t,min(lim,e[i].v));
if(f)
{
e[i].v -= f,e[i^1].v += f;
flow += f,lim -= f;
if(!lim) break;
}
}
if(!flow) dep[s] = -1;
return flow;
}
int dinic(int s,int t)
{
int maxflow = 0;
while(bfs(s,t)) maxflow += dfs(s,t,INF);
return maxflow;
}
int main()
{
Ti = read();
while(Ti--)
{
n = read(),m = read(),T = n + 1;
clear();
rep(i,0,m-1)
{
x = read(),y = read(),a[i] = read(),b[i] = read(),add(x,y,b[i]-a[i]),add(y,x,0);
rsum[y] += a[i],csum[x] += a[i];
}
rep(i,1,n)
{
int now = csum[i] - rsum[i];
if(now < 0) add(S,i,-now),add(i,S,0);
else add(i,T,now),add(T,i,0),tot += now;
}
if(tot != dinic(S,T)) printf("NO\n");
else
{
printf("YES\n");
rep(i,0,m-1) printf("%d\n",e[i<<1|1].v + a[i]);
}
}
return 0;
}
当你意识到,每个上一秒都成为永恒。