1. 程式人生 > >(一道模板題) 無源匯有上下界可行流

(一道模板題) 無源匯有上下界可行流

edi block html else printf ack 分類 tex long long

題目描述

這是一道模板題。

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; }

(一道模板題) 無源匯有上下界可行流