loj115 无源汇有上下界可行流

loj115

1 题目描述

这是一道模板题。

n个点, m条边,每条边 有一个流量下界\(low(e)\)和流量上界\(up(e)\) ,求一种可行方案使得在所有点满足流量平衡条件的前提下,所有边满足流量限制。

2 分析

首先: 我们先把下界的流量放到每条边上去,这样我们就可以算出每个点进入的流量\(in[x]\),流出的流量\(out[x]\)。这条边的剩余容量为\(up-low\)

我们新增一个源点s和汇点t,如果某个点x,\(in[x]>out[x]\),即流入大于流出,我们可以在s到x建一条容量为\(in[x]-out[x]\)的边,反之,如果\(in[x]<out[x]\),我们就在x到t建立一条容量为\(out[x]-in[x]\)的边。

最后我们判断从s到t的最大流是否等于s到其他点的容量总和,如果可以达到,就表明这个可行流是存在的。

3 代码

#include<bits/stdc++.h>
using namespace std;  
int const N=200+5;  
int const M=40000;  
int const inf=1e9;  
struct edge{
	int to,nt,capa,fl,id;   
}e[M];  
int n,m,h[N],cnt,d[N],q[N],low[M],up[M],s,t,work[N],in[N],out[N],res[M];  
void add(int a,int b,int capa,int id){
	e[cnt].to=b; 
	e[cnt].nt=h[a];  
	e[cnt].capa=capa;  
	e[cnt].fl=0;  
	e[cnt].id=id;  
	h[a]=cnt++; 
}
int bfs(){
	memset(d,-1,sizeof(d));  
	int cl=1; q[0]=s; d[s]=0;  
	for(int i=0;i<cl;i++){
		int x=q[i];  
		for(int j=h[x];j!=-1;j=e[j].nt)
			if(e[j].capa>e[j].fl  && d[e[j].to]==-1){
				d[e[j].to]=d[x]+1;  
				q[cl++]=e[j].to; 
			}
	}
	return d[t]>-1;  
} 
int dfs(int x,int flow){
	if(x==t) return flow;  
	for(int &i=work[x];i!=-1;i=e[i].nt){   
		int v=e[i].to,tmp=0;  
		if(e[i].capa>e[i].fl && d[v]==d[x]+1 &&  (tmp=dfs(v,min(flow,e[i].capa-e[i].fl)))){
			e[i].fl+=tmp; 
			e[i^1].fl-=tmp;  
			return tmp;  
		}
	}
	return 0;  
} 
int main(){
	scanf("%d%d",&n,&m); 
	s=0,t=n+1;  
	memset(h,-1,sizeof(h));  
	for(int i=1;i<=m;i++){ 
		int x,y;  
		scanf("%d%d%d%d",&x,&y,&low[i],&up[i]); 
		out[x]+=low[i];  
		in[y]+=low[i]; 
		add(x,y,up[i]-low[i],i);  
		add(y,x,0,-i);  
	} 
	int sum=0;  
	for(int i=1;i<=n;i++)   
		if(in[i]<out[i]) {	
			add(i,t,out[i]-in[i],0);  
			add(t,i,0,0);  
		}else if(in[i]>out[i]){
			add(s,i,in[i]-out[i],0);  
			sum+=in[i]-out[i];  
			add(i,s,0,0);  
		}
	int ans=0; 
	while (bfs()){
		memcpy(work,h,sizeof(h));  
		int tmp;  
		while ((tmp=dfs(s,inf))) ans+=tmp; 
	} 
	if(ans!=sum) printf("NO\n");  
	else {
		printf("YES\n");  
		for(int i=1;i<=n;i++){
			for(int j=h[i];j!=-1;j=e[j].nt){
				if(e[j].id>0){
					res[e[j].id]+=e[j].fl;  
				} 
			}
		}
		for(int i=1;i<=m;i++) 
			cout<<low[i]+res[i]<<endl; 
	}
	return 0; 
}
posted @ 2020-08-18 21:59  zjxxcn  阅读(125)  评论(0编辑  收藏  举报