题目描述
这是一道模板题。
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 <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
#define inf 0x3f3f3f3f
#define ll long long
#define MAXN 30000
using namespace std;
int n,m;//点数、边数
int X[MAXN],y[MAXN];
int sp,tp;//原点、汇点
struct node
{
int v,next;
ll cap;
}mp[MAXN*10];
int pre[MAXN],dis[MAXN],cur[MAXN];//cur为当前弧优化,dis存储分层图中每个点的层数(即到原点的最短距离),pre建邻接表
int cnt=0;
void init()//不要忘记初始化
{
cnt=0;
memset(pre,-1,sizeof(pre));
}
void add(int u,int v,int w)//加边
{
mp[cnt].v=v;
mp[cnt].cap=w;
mp[cnt].next=pre[u];
pre[u]=cnt++;
mp[cnt].v=u;
mp[cnt].cap=0;
mp[cnt].next=pre[v];
pre[v]=cnt++;
}
bool bfs()//建分层图
{
memset(dis,-1,sizeof(dis));
queue<int>q;
while(!q.empty())
q.pop();
q.push(sp);
dis[sp]=0;
int u,v;
while(!q.empty())
{
u=q.front();
q.pop();
for(int i=pre[u];i!=-1;i=mp[i].next)
{
v=mp[i].v;
if(dis[v]==-1&&mp[i].cap>0)
{
dis[v]=dis[u]+1;
q.push(v);
if(v==tp)
break;
}
}
}
return dis[tp]!=-1;
}
ll dfs(int u,ll cap)//寻找增广路
{
if(u==tp||cap==0)
return cap;
ll res=0,f;
for(int &i=cur[u];i!=-1;i=mp[i].next)
{
int v=mp[i].v;
if(dis[v]==dis[u]+1&&(f=dfs(v,min(cap-res,mp[i].cap)))>0)
{
mp[i].cap-=f;
mp[i^1].cap+=f;
res+=f;
if(res==cap)
return cap;
}
}
if(!res)
dis[u]=-1;
return res;
}
ll dinic()
{
ll ans=0;
while(bfs())
{
for(int i=0;i<=tp;i++)
cur[i]=pre[i];
ans+=dfs(sp,inf);
}
return ans;
}
int d[MAXN];
int main()
{
init();
int s,t;
scanf("%d%d%d%d",&n,&m,&s,&t);
int x,y,low,up;
for (int i = 0; i <m ; ++i) {
scanf("%d%d%d%d",&x,&y,&low,&up);
add(x,y,up-low);
d[x]-=low;
d[y]+=low;
}
int sum=0;
for (int i = 1; i <=n ; ++i) {
if(d[i]>0)
{
sum+=d[i];
add(0,i,d[i]);
}
if(d[i]<0)
add(i,n+1,-d[i]);
}
add(t,s,inf);
sp=0;tp=n+1;
int k=dinic();
if(k!=sum)
{
printf("please go home to sleep\n");
} else
{
sp=s;tp=t;
printf("%lld\n",dinic());
}
return 0;
}