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