关于最大流问题,看到了一篇大神写的非常好的博客:点击打开链接
这里面讲的都非常详细了,所以就不多说了,贴代码主要是因为习惯了自己的代码风格……
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <set>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
const int maxn = 10000+10;
const int MAXM = 1000000+10;
const int INF = 0x3f3f3f3f;
int n;
struct Edge {
int v,flow,id,link;
} edge[MAXM];
int head[maxn],tol;
int dis[maxn],du[maxn],dn[MAXM],ans[MAXM];
bool vis[maxn];
void add(int u,int v,int flow,int id) {
edge[tol].v = v,edge[tol].flow = flow,edge[tol].id = id,edge[tol].link = head[u],head[u] = tol++;
edge[tol].v = u,edge[tol].flow = 0,edge[tol].id = 0,edge[tol].link = head[v],head[v] = tol++;
}
bool bfs(int s,int t) {
memset(dis,0,sizeof(dis));
dis[s] = 1;
queue<int>q;
q.push(s);
while(!q.empty()) {
int u = q.front();
q.pop();
if(u == t)return true;
for(int i = head[u]; ~i; i = edge[i].link) {
int v = edge[i].v;
if(!dis[v] && edge[i].flow) {
dis[v] = dis[u] + 1;
q.push(v);
}
}
}
return false;
}
int dfs(int s,int t,int maxf) {
if(s == t)return maxf;
int ret = 0;
for(int i = head[s]; ~i; i = edge[i].link) {
int v = edge[i].v,flow = edge[i].flow;
if(dis[s] + 1 == dis[v] && edge[i].flow) {
int Min = min(maxf-ret,edge[i].flow);
flow = dfs(v,t,Min);
edge[i].flow -= flow;
edge[i^1].flow += flow;
ret += flow;
if(ret == maxf)return ret;
}
}
return ret;
}
int Dinic(int s,int t) {
int ans = 0;
while(bfs(s,t))ans += dfs(s,t,INF);
return ans;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif ONLINE_JUDGE
int u,v,low,up,m;
while(~scanf("%d%d",&n,&m)) {
memset(head,-1,sizeof(head));
memset(dn,0,sizeof(dn));
memset(du,0,sizeof(du));
memset(ans,0,sizeof(ans));
tol = 0;
for(int i = 1; i <= m; i++) {
scanf("%d%d%d%d",&u,&v,&low,&up);
add(u,v,up-low,i);
du[u] -= low;
du[v] += low;
dn[i] = low;
}
int cnt = tol;
for(int i = 1; i <= n; i++) {
if(du[i] > 0)add(0,i,du[i],0);
if(du[i] < 0)add(i,n+1,-du[i],0);
}
int sum = Dinic(0,n+1);
bool flag = true;
for(int i = head[0]; i != -1; i = edge[i].link) {
if(edge[i].flow > 0) {
flag = false;
break;
}
}
if(!flag)puts("NO");
else {
puts("YES");
for(int i = 0; i < cnt; i++)ans[edge[i].id] = edge[i^1].flow;
for(int i = 1; i <= m; i++)
printf("%d\n",ans[i] + dn[i]);
}
}
return 0;
}