题目描述
这是一道模板题n 个点,m 条边,每条边 e 有一个流量下界 lower(e)(和流量上界 upper(e) ,求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。
输入格式
第一行两个正整数 n 、m 。
之后的 m行,每行四个整数 s 、t 、lower 、upper 。
输出格式
如果无解,输出一行 NO
。
否则第一行输出 YES
,之后 m 行每行一个整数,表示每条边的流量。
样例
样例输入 1
4 6
1 2 1 2
2 3 1 2
3 4 1 2
4 1 1 2
1 3 1 2
4 2 1 2
样例输出 1
NO
样例输入 2
4 6
1 2 1 3
2 3 1 3
3 4 1 3
4 1 1 3
1 3 1 3
4 2 1 3
样例输出 2
YES
1
2
3
2
1
1
数据范围与提示
1≤n≤200,1≤m≤10200
题解:
模板题;其实可以就是通过某种建图,然后取跑最大流,可是否满流。
具体建图方式: 建立源点S 汇点T, 每条边建立 x ->y,flow=(最大流)-(最小流),同时建立每个点流入流出情况d[i],即d[x]-=流出,d[y]+=流入,输出是最小流+跑完最大流后每条边上的流量。
#include <bits/stdc++.h>
using namespace std;
const int MAXN=10200+10;
const int MAXM=10200+10;
const int INF=0x3f3f3f3f;
int ss,tt;
struct node{
int v,next,flow;
}edge[MAXN*10];
int head[MAXN],cnt=0,cur[MAXN];
int d[MAXN],st[MAXM];
void ADD(int x,int y,int flow)
{
edge[cnt].v=y;
edge[cnt].flow=flow;
edge[cnt].next=head[x];
head[x]=cnt++;
edge[cnt].v=x;
edge[cnt].flow=0;
edge[cnt].next=head[y];
head[y]=cnt++;
}
int dis[MAXN];
bool bfs()
{
memset(dis,-1, sizeof(dis));
queue<int >qu;
while(!qu.empty())
qu.pop();
qu.push(ss);
dis[ss]=0;
int u,v;
while (!qu.empty())
{
u=qu.front();
qu.pop();
for (int i = head[u]; i !=-1 ; i=edge[i].next) {
v=edge[i].v;
if(dis[v]==-1&&edge[i].flow>0)
{
dis[v]=dis[u]+1;
qu.push(v);
if(v==tt)
break;
}
}
}
return dis[tt]!=-1;
}
int dfs(int u,int cap)
{
if(u==tt||cap==0)
return cap;
int res=0,v,f;
for (int &i = cur[u]; i !=-1; i=edge[i].next) {
v=edge[i].v;
if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,edge[i].flow)))>0)
{
edge[i].flow-=f;
edge[i^1].flow+=f;
res+=f;
if(res==cap)
return cap;
}
}
if(!res)
dis[u]=-1;
return res;
}
int dinic()
{
int ans=0;
while(bfs())
{
for (int i = 0; i <=tt ; ++i) {
cur[i]=head[i];
}
ans+=dfs(ss,INF);
}
return ans;
}
int main()
{
int n,m;
memset(head,-1, sizeof(head));
memset(d,0, sizeof(d)); memset(st,0, sizeof(st));
scanf("%d%d",&n,&m);
ss=0;tt=n+1;
int x,y,low,up;
for (int i = 0; i <m ; ++i) {
scanf("%d%d%d%d",&x,&y,&low,&up);
ADD(x,y,up-low);
d[x]-=low;
d[y]+=low;
st[i]=low;
}
int sum=0;
for (int i = 1; i <=n ; ++i) {
if(d[i]>0)
sum+=d[i];
ADD(ss,i,d[i]);
if(d[i]<0)
ADD(i,tt,-d[i]);
}
if(dinic()!=sum)
{
printf("NO\n");
return 0;
} else
{
printf("YES\n");
for (int i = 0; i <m ; ++i) {
printf("%d\n",edge[i*2|1].flow+st[i]);
}
}
return 0;
}
//loj115