(一道模板题) 无源汇有上下界可行流
这是一道模板题。
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
数据范围与提示
N<=200,M<=10200
分类标签
码了一天了懒得再打一下上下界网络流原理来,,,就是一个流量平衡。
#include<bits/stdc++.h> #define ll long long #define maxn 1005 #define pb push_back using namespace std; const int inf=1<<29; vector<int> g[maxn]; struct lines{ int to,flow,cap; }l[maxn*maxn]; int t=-1,S,T,n,m; int d[maxn],cur[maxn]; bool v[maxn]; inline void add(int xx,int yy,int zz){ l[++t]=(lines){yy,0,zz},g[xx].pb(t); l[++t]=(lines){xx,0,0},g[yy].pb(t); } inline bool bfs(){ queue<int> q; memset(v,0,sizeof(v)); d[S]=0,v[S]=1,q.push(S); int x; lines e; while(!q.empty()){ x=q.front(),q.pop(); for(int i=g[x].size()-1;i>=0;i--){ e=l[g[x][i]]; if(!v[e.to]&&e.flow<e.cap){ d[e.to]=d[x]+1; v[e.to]=1; q.push(e.to); } } } return v[T]; } int dfs(int x,int a){ if(x==T||!a) return a; int flow=0,f,sz=g[x].size(); for(int &i=cur[x];i<sz;i++){ lines &e=l[g[x][i]]; if(d[x]==d[e.to]-1&&(f=dfs(e.to,min(a,e.cap-e.flow)))){ flow+=f,a-=f; e.flow+=f,l[g[x][i]^1].flow-=f; if(!a) break; } } return flow; } inline int max_flow(){ int an=0; while(bfs()){ memset(cur,0,sizeof(cur)); an+=dfs(S,inf); } return an; } int low[maxn*50],inflow[maxn],tot=0; int main(){ int uu,vv,r; scanf("%d%d",&n,&m); for(int i=0;i<m;i++){ scanf("%d%d%d%d",&uu,&vv,low+i,&r); add(uu,vv,r-low[i]); inflow[vv]+=low[i]; inflow[uu]-=low[i]; } S=0,T=n+1; for(int i=1;i<=n;i++){ if(inflow[i]>0){ add(S,i,inflow[i]); tot+=inflow[i]; } else if(inflow[i]) add(i,T,-inflow[i]); } if(tot!=max_flow()) puts("NO"); else{ puts("YES"); for(int i=0;i<m;i++) printf("%d\n",low[i]+l[i<<1].flow); } return 0; }
我爱学习,学习使我快乐