1. 程式人生 > >有上下界的網路流 模板

有上下界的網路流 模板

#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

1≤n≤202,1≤m≤9999

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