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


    题目描述

    这是一道模板题。

    n个点,m  条边,每条边 e 有一个流量下界 lower(e)  和流量上界 upper(e) ),给定源点 s 与汇点 t,求源点到汇点的最大流。

    输入格式

    第一行两个正整数 nmst

    之后的 m 行,每行四个整数 stlowerupper

    输出格式

    如果无解,输出一行 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
    ");
        } else
        {
            sp=s;tp=t;
            printf("%lld
    ",dinic());
        }
        return 0;
    }
    

      

  • 相关阅读:
    Linux进程间通信:父子进程通过信号通信,实现交替数数,时间间隔1秒
    Ubuntu18 给terminal改个漂亮的命令行提示符
    int型、char*、string、的swap算法
    C++中的友元函数的总结
    C++内联函数
    static作用,静态成员变量和静态成员函数
    9——对象的创建和撤销,构造函数和析构函数
    如何用敏捷搞垮一个团队?
    .Net核心中间件httpContext不支持并发读写 Concurrent reads or writes are not supported.
    CentOS 7 MySQL5.7 多实例(多端口)
  • 原文地址:https://www.cnblogs.com/-xiangyang/p/9783919.html
Copyright © 2020-2023  润新知