其他分享
首页 > 其他分享> > LOJ#116. 有源汇有上下界最大流

LOJ#116. 有源汇有上下界最大流

作者:互联网

在无源汇可行流的基础上加一条源点到汇点流量inf的边,然后(虚源点到虚汇点)跑最大流,汇点到源点流经的流量就是有源汇可行流x
然后删除多加的源点到汇点的边,再从源点到汇点跑最大流,得到最大流y,x+y就是有源汇有上下界最大流

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const ll maxn =505;
const ll inf=1e18;
ll head[maxn],cnt;
struct E
{
	ll to,next,flow;
}e[maxn*maxn];
ll nex[maxn],dis[maxn];
void add(ll u,ll v,ll flow)
{
	e[cnt].to=v;
	e[cnt].flow=flow;
	e[cnt].next=head[u];
	head[u]=cnt++;
	
	e[cnt].to=u;
	e[cnt].flow=0;
	e[cnt].next=head[v];
	head[v]=cnt++;
	
}
ll n,m,st,ed,d[maxn],num=0;
void init()
{
	cnt=0;
	memset(head,-1,sizeof(head));
}
queue<ll>q;
bool bfs()
{
	while(!q.empty()) q.pop();
	for(ll i=0;i<=ed+1;i++) nex[i]=head[i],dis[i]=inf;
	q.push(st);dis[st]=0;
	while(!q.empty())
	{
		int u=q.front();q.pop();
		//printf("u=%d\n",u);
		for(ll i=head[u];i!=-1;i=e[i].next)
		{
			ll v=e[i].to,flow=e[i].flow;
			//printf(" v=%d flow=%d\n",v,flow);
			if((flow>0)&&(dis[v]==inf))
			{
				
				dis[v]=dis[u]+1;
				q.push(v);
				if(v==ed) return 1;
			}
		}
	}
	return 0;
}
ll dfs(ll u,ll w)
{
	if(u==ed) return w;
	ll y=0;
	for(ll i=nex[u];(i!=-1)&&w;i=e[i].next)
	{
		nex[u]=i;
		ll v=e[i].to,flow=e[i].flow;
		if((flow>0)&&(dis[u]+1==dis[v]))
		{
			ll k=dfs(v,min(flow,w));
			if(k==0) dis[v]=inf;
			y+=k;
			w-=k;
			e[i].flow-=k;
			e[i^1].flow+=k;
		}
	}
	return y;
}
ll slove()
{
	ll ans=0;
	while(bfs())
	{
		//for(int i=0;i<=ed;i++) printf("dis[%d]=%d\n",i,dis[i]);
		ans+=dfs(st,inf);
		//printf("-ans=%d\n",ans);
	}
	return ans;
}
int main()
{
	ll s1,t1;
	scanf("%lld %lld %lld %lld",&n,&m,&s1,&t1);
	init();st=0,ed=n+1;
	for(ll i=1;i<=m;i++)
	{
		ll u,v,x,y;
		scanf("%lld %lld %lld %lld",&u,&v,&x,&y);
		add(u,v,y-x);
		d[u]-=x;d[v]+=x;
	}
	
	num=0;
	for(ll i=1;i<=n;i++)
	{
		if(d[i]>0) add(st,i,d[i]),num+=d[i];
		if(d[i]<0) add(i,ed,-d[i]);
	}add(t1,s1,inf);
	ll ans=slove();
	//printf("ans=%lld\n",ans);
	if(ans!=num)
	{
		printf("please go home to sleep\n");
		return 0;
	}
	st=s1,ed=t1;
	ans=e[cnt].flow;
	e[cnt].flow=e[cnt^1].flow=0;
	ans+=slove();
	printf("%lld\n",ans);
	return 0;
} 

标签:cnt,LOJ,ll,flow,head,116,maxn,汇有,dis
来源: https://www.cnblogs.com/League-of-cryer/p/14122239.html