有上下界网络流模板
115. 无源汇有上下界可行流
n 个点,m 条边,每条边 e 有一个流量下界 lower(e)和流量上界 upper(e)),求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。
输入格式
第一行两个正整数 n 、m 。
之后的 m 行,每行四个整数 s、t 、lower 、upper。
输出格式
如果无解,输出一行 NO
。
否则第一行输出 YES
,之后 m 行每行一个整数,表示每条边的流量。
#include<bits/stdc++.h> using namespace std; const int maxn=70005; int sp,tp,cnt=0,head[205],nxt[maxn],to[maxn],cap[maxn],dis[1005],low[maxn],def[205],m,n; inline int read(){ int ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } inline void add(int u,int v,int p){ nxt[cnt]=head[u],to[cnt]=v,cap[cnt]=p,head[u]=cnt++; nxt[cnt]=head[v],to[cnt]=u,cap[cnt]=0,head[v]=cnt++; } inline bool bfs(){ int u,e,v; queue<int> que; memset(dis,-1,sizeof(dis)); que.push(sp),dis[sp]=0; while(!que.empty()){ u=que.front(),que.pop(); for(int e=head[u];~e;e=nxt[e]){ if(cap[e]>0&&dis[v=to[e]]==-1){ dis[v]=dis[u]+1,que.push(v); if(v==tp) return true; } } } return false; } inline int dfs(const int &u,const int &flow){ if(u==tp) return flow; int res=0,v,flw; for(int e=head[u];~e;e=nxt[e]){ if(cap[e]>0&&dis[u]<dis[v=to[e]]){ flw=dfs(v,min(cap[e],flow-res)); if(flw==0) dis[v]=-1; cap[e]-=flw,cap[e^1]+=flw; res+=flw; if(res==flow) break; } } return res; } inline int dinic(int sp,int tp){ int ans=0; while(bfs()) { ans+=dfs(sp,1<<30); } return ans; } int main(){ memset(head,-1,sizeof(head)); n=read(),m=read(); int s,t,up,down,sum=0; for(int i=1;i<=m;i++){ s=read(),t=read(),down=read(),up=read(); add(s,t,up-down); low[i]=down,def[s]+=down,def[t]-=down; } sp=n+1,tp=n+2; for(int i=1;i<=n;i++){ if(def[i]>0) sum+=def[i],add(i,tp,def[i]); if(def[i]<0) add(sp,i,-def[i]); } if(dinic(sp,tp)==sum){ cout<<"YES"<<endl; for(int i=1;i<=m;i++){ cout<<cap[((i-1)*2)^1]+low[i]<<endl; } } else cout<<"NO"<<endl; return 0; }
#116. 有源汇有上下界最大流
n 个点,m 条边,每条边 e 有一个流量下界 lower(e)和流量上界 upper(e) ,给定源点 s 与汇点 t ,求源点到汇点的最大流。
输入格式
第一行两个正整数 n、m、s、t。
之后的 m 行,每行四个整数 s、t、lower、upper。
输出格式
如果无解,输出一行 please go home to sleep
。
否则输出最大流。
样例输入
-
10 15 9 10
-
9 1 17 18
-
9 2 12 13
-
9 3 11 12
-
1 5 3 4
-
1 6 6 7
-
1 7 7 8
-
2 5 9 10
-
2 6 2 3
-
2 7 0 1
-
3 5 3 4
-
3 6 1 2
-
3 7 6 7
-
5 10 16 17
-
6 10 10 11
-
7 10 14 15
样例输出
43
#include<bits/stdc++.h> using namespace std; const int maxn=70005; int sp,tp,cnt=1,head[205],nxt[maxn],to[maxn],cap[maxn],dis[1005],low[maxn],st,de,def[205],m,n; inline int read(){ int ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } inline void addedge(int u,int v,int p){ nxt[++cnt]=head[u],head[u]=cnt,to[cnt]=v,cap[cnt]=p; nxt[++cnt]=head[v],head[v]=cnt,to[cnt]=u,cap[cnt]=0; } inline bool bfs(){ int u,e,v; queue<int> que; memset(dis,-1,sizeof(dis)); que.push(sp),dis[sp]=0; while(!que.empty()){ u=que.front(),que.pop(); for(int e=head[u];e;e=nxt[e]){ if(cap[e]>0&&dis[v=to[e]]==-1){ dis[v]=dis[u]+1,que.push(v); if(v==tp) return true; } } } return false; } inline int dfs(const int &u,const int &flow){ if(u==tp) return flow; int res=0,v,flw; for(int e=head[u];e;e=nxt[e]){ if(cap[e]>0&&dis[u]<dis[v=to[e]]){ flw=dfs(v,min(cap[e],flow-res)); if(flw==0) dis[v]=-1; cap[e]-=flw,cap[e^1]+=flw; res+=flw;if(res==flow) break; } } return res; } inline int dinic(int sp,int tp){ int ans=0; while(bfs()) { ans+=dfs(sp,1<<30); } return ans; } int main(){ memset(head,-1,sizeof(head)); n=read(),m=read(),st=read(),de=read(); int s,t,up,down,sum=0; for(int i=1;i<=m;i++){ s=read(),t=read(),down=read(),up=read(); addedge(s,t,up-down); low[i]=down,def[s]+=down,def[t]-=down; } sp=n+1,tp=n+2; for(int i=1;i<=n;i++){ if(def[i]>0) sum+=def[i],addedge(i,tp,def[i]); if(def[i]<0) addedge(sp,i,-def[i]); } addedge(de,st,1<<30); if(dinic(sp,tp)==sum){ head[sp]=0,head[tp]=0; sp=st; tp=de; cout<<dinic(sp,tp)<<endl; } else cout<<"please go home to sleep"<<endl; return 0; }
#include<bits/stdc++.h> using namespace std; const int maxn=70005; int sp,tp,cnt=1,head[205],nxt[maxn],to[maxn],cap[maxn],dis[1005],low[maxn],st,de,def[205],m,n; inline int read(){ int ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } inline void addedge(int u,int v,int p){ nxt[++cnt]=head[u],head[u]=cnt,to[cnt]=v,cap[cnt]=p; nxt[++cnt]=head[v],head[v]=cnt,to[cnt]=u,cap[cnt]=0; } inline bool bfs(){ int u,e,v; queue<int> que; memset(dis,-1,sizeof(dis)); que.push(sp),dis[sp]=0; while(!que.empty()){ u=que.front(),que.pop(); for(int e=head[u];e;e=nxt[e]){ if(cap[e]>0&&dis[v=to[e]]==-1){ dis[v]=dis[u]+1,que.push(v); if(v==tp) return true; } } } return false; } inline int dfs(const int &u,const int &flow){ if(u==tp) return flow; int res=0,v,flw; for(int e=head[u];e;e=nxt[e]){ if(cap[e]>0&&dis[u]<dis[v=to[e]]){ flw=dfs(v,min(cap[e],flow-res)); if(flw==0) dis[v]=-1; cap[e]-=flw,cap[e^1]+=flw; res+=flw;if(res==flow) break; } } return res; } inline int dinic(int sp,int tp){ int ans=0; while(bfs()) { ans+=dfs(sp,1<<30); } return ans; } int main(){ memset(head,-1,sizeof(head)); n=read(),m=read(),st=read(),de=read(); int s,t,up,down,sum=0; for(int i=1;i<=m;i++){ s=read(),t=read(),down=read(),up=read(); addedge(s,t,up-down); low[i]=down,def[s]+=down,def[t]-=down; } sp=n+1,tp=n+2; for(int i=1;i<=n;i++){ if(def[i]>0) sum+=def[i],addedge(i,tp,def[i]); if(def[i]<0) addedge(sp,i,-def[i]); } addedge(de,st,1<<30); if(dinic(sp,tp)==sum){ head[sp]=0,head[tp]=0; sp=st; tp=de; cout<<dinic(sp,tp)<<endl; } else cout<<"please go home to sleep"<<endl; return 0; }
#117. 有源汇有上下界最小流
n 个点,m 条边,每条边 e 有一个流量下界 lower(e) 和流量上界 upper(e),给定源点 s 与汇点 t,求源点到汇点的最小流。
输入格式
第一行两个正整数 n、m、s、t。
之后的 m 行,每行四个整数 s、t、lower、upper。
输出格式
如果无解,输出一行 please go home to sleep
。
否则输出最小流。
样例输入
-
7 12 6 7
-
6 1 0 2147483647
-
1 7 0 2147483647
-
6 2 0 2147483647
-
2 7 0 2147483647
-
6 3 0 2147483647
-
3 7 0 2147483647
-
6 4 0 2147483647
-
4 7 0 2147483647
-
6 5 0 2147483647
-
5 7 0 2147483647
-
5 1 1 2147483647
-
3 4 1 2147483647
样例输出
2
#include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<cstdlib> #include<iostream> #include<queue> #define inf 0x7fffffff using namespace std; const int maxn=50010; const int maxm=405000; int n,m,sp,tp,s,t; int nxt[maxm],head[maxn],to[maxm],cap[maxm],cnt=0,deg[maxn]; int cur[maxm],dis[maxm]; inline int read(){ int ans=0; char last=' ',ch=getchar(); while(ch<'0' || ch>'9')last=ch,ch=getchar(); while(ch>='0' && ch<='9')ans=ans*10+ch-'0',ch=getchar(); if(last=='-')ans=-ans; return ans; } inline void add(int u,int v,int p){ nxt[cnt]=head[u],to[cnt]=v,cap[cnt]=p,head[u]=cnt++; nxt[cnt]=head[v],to[cnt]=u,cap[cnt]=0,head[v]=cnt++; } bool bfs(int st,int en){ memset(dis,-1,sizeof(dis)); memcpy(cur,head,sizeof(head)); queue<int > q; q.push(st);dis[st]=0; while(!q.empty()){ int u=q.front();q.pop(); for(int e=head[u];~e;e=nxt[e]){ int v=to[e]; if(cap[e]>0&&dis[v]==-1){ dis[v]=dis[u]+1; if(v==en) return true; q.push(v); } } } return false; } inline int dinic(int u,int flow,int ee){ if(u==ee) return flow; int res=0; for(int &e=cur[u];~e;e=nxt[e]){ int v=to[e]; if(cap[e]>0&&dis[v]>dis[u]){ int delta=dinic(v,min(flow-res,cap[e]),ee); if(delta){ cap[e]-=delta;cap[e^1]+=delta; res+=delta; if(res==flow) break; } } } return res; } int main(){ memset(head,-1,sizeof(head)); n=read();m=read();s=read();t=read(); int i,j,k; sp=0;tp=n+1; for(i=1;i<=m;++i){ int u=read(),v=read(),ll=read(),rr=read(); add(u,v,rr-ll); deg[v]+=ll; deg[u]-=ll; } int sum=0,first; add(t,s,inf); first=cnt-1; for(i=1;i<=n;++i){ if(deg[i]<0) add(i,tp,-deg[i]); else if(deg[i]>0) add(sp,i,deg[i]),sum+=deg[i]; } int maxflow=0; while(bfs(sp,tp)) maxflow+=dinic(sp,inf,tp); if(maxflow==sum){ maxflow=cap[first]; for(i=first-1;i<=cnt;++i) cap[i]=0; while(bfs(t,s)) maxflow-=dinic(t,inf,s); printf("%d\n",maxflow); } else printf("please go home to sleep\n"); return 0; }