(一)#116. 有源汇有上下界最大流

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const int p=998244353;
const int mod=998244353;
const int g=3;
const int maxn=410;
const int maxm=40010;
int head[maxn],ver[maxm],edge[maxm],nt[maxm];
int d[maxn],in[maxn],out[maxn];
int n,m,s,t,tot=1,nows,nowt,ss,tt;
queue<int>q;


void add(int x,int y,int z)
{
    ver[++tot]=y,edge[tot]=z,nt[tot]=head[x],head[x]=tot;
    ver[++tot]=x,edge[tot]=0,nt[tot]=head[y],head[y]=tot;
}

bool bfs(void)
{
    memset(d,0,sizeof(d));
    while(q.size()) q.pop();

    q.push(s);
    d[s]=1;

    while(q.size())
    {
        int x=q.front();
        q.pop();

        for(int i=head[x];i;i=nt[i])
        {
            int y=ver[i];
            if(edge[i]&&!d[y])
            {
                q.push(y);
                d[y]=d[x]+1;
                if(y==t) return true;
            }
        }
    }
    return false;
}

int dinic(int x,int flow)
{
    if(x==t) return flow;
    int rest=flow ,k;

    for(int i=head[x];i&&rest;i=nt[i])
    {
        int y=ver[i];
        if(edge[i]&&d[y]==d[x]+1)
        {
            k=dinic(y,min(rest,edge[i]));
            if(!k) d[y]=0;
            edge[i]-=k;
            edge[i^1]+=k;
            rest-=k;
        }
    }
    return flow-rest;
}

int getmaxx(void)
{
    int maxflow=0;
    int flow=0;
    while(bfs())
        while(flow=dinic(s,inf))
            maxflow+=flow;
    return maxflow;
}

void fail(void)
{
    puts("please go home to sleep");
}

int main(void)
{
    scanf("%d%d%d%d",&n,&m,&nows,&nowt);
    int x,y,lo,up;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x,&y,&lo,&up);
        out[x]+=lo,in[y]+=lo;
        add(x,y,up-lo);
    }
    ss=n+1,tt=n+2;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(in[i]>out[i]) add(ss,i,in[i]-out[i]);
        else add(i,tt,out[i]-in[i]);
        sum+=max(in[i]-out[i],0);
    }

    add(nowt,nows,inf);

    int ans=0;
    s=ss,t=tt;

    if(getmaxx()!=sum)
    {
        fail();
        return 0;
    }

    ans+=edge[tot];
    edge[tot]=edge[tot^1]=0;

    s=nows,t=nowt;
    ans+=getmaxx();
    printf("%d\n",ans);

    return 0;
}

(二)#117. 有源汇有上下界最小流

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const int p=998244353;
const int mod=998244353;
const int g=3;
const int maxn=50010;
const int maxm=400100;
int head[maxn],ver[maxm],edge[maxm],nt[maxm];
int d[maxn],in[maxn],out[maxn];
int n,m,s,t,tot=1,nows,nowt,ss,tt;
queue<int>q;


void add(int x,int y,int z)
{
    ver[++tot]=y,edge[tot]=z,nt[tot]=head[x],head[x]=tot;
    ver[++tot]=x,edge[tot]=0,nt[tot]=head[y],head[y]=tot;
}

bool bfs(void)
{
    memset(d,0,sizeof(d));
    while(q.size()) q.pop();

    q.push(s);
    d[s]=1;

    while(q.size())
    {
        int x=q.front();
        q.pop();

        for(int i=head[x];i;i=nt[i])
        {
            int y=ver[i];
            if(edge[i]&&!d[y])
            {
                q.push(y);
                d[y]=d[x]+1;
                if(y==t) return true;
            }
        }
    }
    return false;
}

int dinic(int x,int flow)
{
    if(x==t) return flow;
    int rest=flow ,k;

    for(int i=head[x];i&&rest;i=nt[i])
    {
        int y=ver[i];
        if(edge[i]&&d[y]==d[x]+1)
        {
            k=dinic(y,min(rest,edge[i]));
            if(!k) d[y]=0;
            edge[i]-=k;
            edge[i^1]+=k;
            rest-=k;
        }
    }
    return flow-rest;
}

int getmaxx(void)
{
    int maxflow=0;
    int flow=0;
    while(bfs())
        while(flow=dinic(s,inf))
            maxflow+=flow;
    return maxflow;
}

void fail(void)
{
    puts("please go home to sleep");
}

int main(void)
{
    scanf("%d%d%d%d",&n,&m,&nows,&nowt);
    int x,y,lo,up;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x,&y,&lo,&up);
        out[x]+=lo,in[y]+=lo;
        add(x,y,up-lo);
    }
    ss=n+1,tt=n+2;
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        if(in[i]>out[i]) add(ss,i,in[i]-out[i]);
        else add(i,tt,out[i]-in[i]);
        sum+=max(in[i]-out[i],0);
    }

    add(nowt,nows,inf);

    int ans=0;
    s=ss,t=tt;

    if(getmaxx()!=sum)
    {
        fail();
        return 0;
    }

    ans+=edge[tot];
    edge[tot]=edge[tot^1]=0;

    s=nowt,t=nows;
    ans-=getmaxx();
    printf("%d\n",ans);

    return 0;
}

(三)P5192 Zoj3229 Shoot the Bullet|东方文花帖|【模板】有源汇上下界最大流

注意:少女编号从0开始。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
#include<queue>
#define ll long long
#define llu unsigned ll
using namespace std;
const int inf=0x3f3f3f3f;
const int p=998244353;
const int mod=998244353;
//const int g=3;
const int maxn=410;
const int maxm=1100;
int head[maxn+maxm],ver[maxn*maxm],edge[maxn*maxm],nt[maxn*maxm];
int d[maxn+maxm],in[maxn+maxm],out[maxn+maxm];
int n,m,s,t,tot=1,nows,nowt,ss,tt;
queue<int>q;
int nd[maxn],ng[maxm],cnt=0;

void add(int x,int y,int z)
{
    ver[++tot]=y,edge[tot]=z,nt[tot]=head[x],head[x]=tot;
    ver[++tot]=x,edge[tot]=0,nt[tot]=head[y],head[y]=tot;
}

bool bfs(void)
{
    memset(d,0,sizeof(d));
    while(q.size()) q.pop();

    q.push(s);
    d[s]=1;

    while(q.size())
    {
        int x=q.front();
        q.pop();

        for(int i=head[x];i;i=nt[i])
        {
            int y=ver[i];
            if(edge[i]&&!d[y])
            {
                q.push(y);
                d[y]=d[x]+1;
                if(y==t) return true;
            }
        }
    }
    return false;
}

int dinic(int x,int flow)
{
    if(x==t) return flow;
    int rest=flow ,k;

    for(int i=head[x];i&&rest;i=nt[i])
    {
        int y=ver[i];
        if(edge[i]&&d[y]==d[x]+1)
        {
            k=dinic(y,min(rest,edge[i]));
            if(!k) d[y]=0;
            edge[i]-=k;
            edge[i^1]+=k;
            rest-=k;
        }
    }
    return flow-rest;
}

int getmaxx(void)
{
    int maxflow=0;
    int flow=0;
    while(bfs())
        while(flow=dinic(s,inf))
            maxflow+=flow;
    return maxflow;
}

void fail(void)
{
    puts("-1\n");
}

int main(void)
{
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        memset(head,0,sizeof(head));
        memset(in,0,sizeof(in));
        memset(out,0,sizeof(out));
        tot=1,cnt=0;
        for(int i=1;i<=n;i++) nd[i]=++cnt;
        for(int i=0;i<m;i++) ng[i]=++cnt;
        nows=++cnt,nowt=++cnt,ss=cnt+1,tt=ss+1;

        int gg;
        for(int i=0;i<m;i++)
        {
            scanf("%d",&gg);
            out[ng[i]]+=gg,in[nowt]+=gg;
            add(ng[i],nowt,inf-gg);
        }

        int cc,dd;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&cc,&dd);
            out[nows]+=0,in[nd[i]]+=0;
            add(nows,nd[i],dd);

            int t,l,r;
            for(int j=1;j<=cc;j++)
            {
                scanf("%d%d%d",&t,&l,&r);
                out[nd[i]]+=l,in[ng[t]]+=l;
                add(nd[i],ng[t],r-l);
            }
        }

        int sum=0;
        for(int i=1;i<=cnt;i++)
        {
            if(in[i]>out[i]) add(ss,i,in[i]-out[i]);
            else add(i,tt,out[i]-in[i]);
            sum+=max(in[i]-out[i],0);
        }
        add(nowt,nows,inf);

        s=ss,t=tt;
        if(getmaxx()!=sum)
        {
            fail();
            continue;
        }

        int ans=edge[tot];
        edge[tot]=edge[tot^1]=0;
        s=nows,t=nowt;
        ans+=getmaxx();
        printf("%d\n\n",ans);
    }

    return 0;
}