【题目链接】

http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=20757

【题意】

求有容量上下界的无源无汇可行流。

【思路】

无源无汇可行流要求所有的顶点都满足流量平衡。

基本思路是转化成最大流来做。

对于边(u,v,b,c),连边(u,v,c-b)。为了保持流量平衡,我们还需要连边
        1.(S,u,inB[u]-outB[u])  inB>outB

2.(u,T,outB[u]-inB[u])  outB>inB

S->T跑一遍最大流,如果S的出边或T的入边满载则有解。

【代码】

 #include<set>
#include<cmath>
#include<queue>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define trav(u,i) for(int i=front[u];i;i=e[i].nxt)
#define FOR(a,b,c) for(int a=(b);a<=(c);a++)
using namespace std; typedef long long ll;
const int N = 4e2+;
const int M = N*N+;
const int inf = 1e9; ll read() {
char c=getchar();
ll f=,x=;
while(!isdigit(c)) {
if(c=='-') f=-; c=getchar();
}
while(isdigit(c))
x=x*+c-'',c=getchar();
return x*f;
} struct Edge {
int u,v,cap,flow;
};
struct Dinic {
int n,m,s,t;
int d[N],cur[N],vis[N];
vector<int> g[N];
vector<Edge> es;
queue<int> q;
void init(int n) {
this->n=n;
es.clear();
FOR(i,,n) g[i].clear();
}
void clear() {
FOR(i,,(int)es.size()-) es[i].flow=;
}
void AddEdge(int u,int v,int w) {
es.push_back((Edge){u,v,w,});
es.push_back((Edge){v,u,,});
m=es.size();
g[u].push_back(m-);
g[v].push_back(m-);
}
int bfs() {
memset(vis,,sizeof(vis));
q.push(s); d[s]=; vis[s]=;
while(!q.empty()) {
int u=q.front(); q.pop();
FOR(i,,(int)g[u].size()-) {
Edge& e=es[g[u][i]];
int v=e.v;
if(!vis[v]&&e.cap>e.flow) {
vis[v]=;
d[v]=d[u]+;
q.push(v);
}
}
}
return vis[t];
}
int dfs(int u,int a) {
if(u==t||!a) return a;
int flow=,f;
for(int& i=cur[u];i<g[u].size();i++) {
Edge& e=es[g[u][i]];
int v=e.v;
if(d[v]==d[u]+&&(f=dfs(v,min(a,e.cap-e.flow)))>) {
e.flow+=f;
es[g[u][i]^].flow-=f;
flow+=f; a-=f;
if(!a) break;
}
}
return flow;
}
int MaxFlow(int s,int t) {
this->s=s,this->t=t;
int flow=;
while(bfs()) {
memset(cur,,sizeof(cur));
flow+=dfs(s,inf);
}
return flow;
}
} dc; int n,m,sum,B[M],INB[N],OUTB[N]; int main()
{
n=read(),m=read();
dc.init(n+);
int S=,T=n+;
FOR(i,,m) {
int u=read(),v=read(),b=read(),c=read();
dc.AddEdge(u,v,c-b);
B[i]=b;
INB[v]+=b,OUTB[u]+=b;
}
FOR(i,,n) {
int c=INB[i]-OUTB[i];
if(c>) dc.AddEdge(S,i,c),sum+=c;
else dc.AddEdge(i,T,-c);
}
if(dc.MaxFlow(S,T)!=sum) puts("NO");
else {
puts("YES");
FOR(i,,m-) printf("%d\n",dc.es[i*].flow+B[i+]);
}
return ;
}
04-13 10:19