#115. 无源汇有上下界可行流(模板)
题目描述
这是一道模板题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