2314 Reactor Cooling(有上下界網路流)
阿新 • • 發佈:2018-12-21
題目:
給n個點和m個邊,每條邊有流量上界和下界,問能否使這n個點形成一個流量迴圈,每個點流入等於流出,每條邊都在界限之內。
分析:
典型的有上下界無源匯網路流。
法一:
建立源點 和匯點 , 對於圖中每條邊 ,拆成如下三條:
- ,容量為
- ,容量為
- ,容量為
其中前兩條弧一般稱為附加弧。
然後對圖跑從 到 的最大流,如果所有附加弧都滿流,則有可行流。這時,每條非附加弧的流量加上它的容量下界,就是原圖中這條弧應該有的流量。
法二:
建立源點 和匯點 ,對於每條邊建立 容量為 的邊。此外,對於圖中每個點,令 。
若 , 建立 容量為 的邊。
若 ,建立 容量為 的邊。
然後跑 到 的最大流,若附加邊全部滿流,即 之和,存在可行流。每條邊流量同法一。
其實法一和法二本質是一樣的,但法二建立的邊更少,速度更快。
程式碼:
#include <bits/stdc++.h>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
#define lson rt*2,l,(l+r)/2
#define rson rt*2+1,(l+r)/2+1,r
typedef unsigned long long ull;
typedef long long ll;
const int MAXN = 205;
const int MAXM = 100005;
const int INF=0x3f3f3f3f;
int read(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x*=10;x+=ch-'0';ch=getchar();}
return x*f;
}
struct Edge{
int to,next,cap,flow;
int id;
}edge[MAXM];
int tot,head[MAXN];
int Q[MAXN],cur[MAXN],dep[MAXN];
int n,m,S,T,N,to[MAXN];
void init(){
tot = 2;
memset(head,-1,sizeof head);
}
void addedge(int u, int v, int w, int id, int rw = 0) {
edge[tot].to = v; edge[tot].cap = w; edge[tot].flow = 0; edge[tot].id = id;
edge[tot].next = head[u]; head[u] = tot++;
edge[tot].to = u; edge[tot].cap = rw; edge[tot].flow = 0; edge[tot].id = -1;
edge[tot].next = head[v]; head[v] = tot++;
}
bool bfs(int s,int t,int n){
int Front = 0, tail = 0;
memset(dep,-1,sizeof(dep[0])*(n+1));
dep[s] = 0;
Q[tail++] = s;
while(Front < tail){
int u = Q[Front++];
for(int i=head[u];i!=-1;i=edge[i].next){
int v=edge[i].to;
if(edge[i].cap > edge[i].flow && dep[v] == -1){
dep[v] = dep[u]+1;
if(v==t) return true;
Q[tail++] = v;
}
}
}
return false;
}
int dfs(int u,int f){
if(u==T) return f;
int used = 0, rflow = 0;
for(int i=cur[u];i!=-1;i=edge[i].next){
cur[u] = i;
int v = edge[i].to, w = edge[i].cap - edge[i].flow;
if (w>0 && dep[v] == dep[u]+1){
if((rflow=dfs(v,min(w,f-used)))){
used+=rflow;
edge[i].flow += rflow;
edge[i^1].flow -= rflow;
if(used == f) break;
}
}
}
if(!used) dep[u] = -1;
return used;
}
int dinic(int s,int t,int n){
int maxflow = 0;
while(bfs(s,t,n)){
for(int i=0;i<=n;i++) cur[i] = head[i];
maxflow += dfs(s,INF);
}
return maxflow;
}
int low[MAXM], d[MAXN], id[MAXM];
int main(){
// freopen("cooling.in","r",stdin);
// freopen("cooling.out","w",stdout);
int kase;
kase = read();
while(kase--) {
n = read(); m = read();
init();
for(int i=0;i<=n;i++) d[i] = 0;
for(int i=0;i<=m;i++) id[i] = 0;
S = 0, T = n + 1, N = n + 1;
for(int i=1;i<=m;i++) {
int u,v,l,r; u = read(); v = read(); l = read(); r = read();
addedge(u,v,r-l,i);
low[i] = l;
d[u] -= l; d[v] += l;
id[i] = tot-2;
}
int sum = 0;
for(int i=1;i<=n;i++) {
if(d[i] > 0 ) {
sum += d[i];
addedge(S,i,d[i],-1);
}else if(d[i] < 0 ) {
addedge(i,T,-d[i],-1);
}
}
if(dinic(S,T,N) == sum) {
puts("YES");
for(int i=1;i<=m;i++) {
printf("%d\n",low[i] + edge[id[i]].flow);
}
}else {
puts("NO");
}
puts("");
}
return 0;
}