zoukankan      html  css  js  c++  java
  • #117. 有源汇有上下界最小流

    题目描述

    n nn 个点,m mm 条边,每条边 e ee 有一个流量下界 lower(e) ext{lower}(e)lower(e) 和流量上界 upper(e) ext{upper}(e)upper(e),给定源点 s ss 与汇点 t tt,求源点到汇点的最小流。

    输入格式

    第一行两个正整数 n nn、m mm、s ss、t tt。

    之后的 m mm 行,每行四个整数 s ss、t tt、lower ext{lower}lower、upper ext{upper}upper。

    输出格式

    如果无解,输出一行 please go home to sleep

    否则输出最小流。

    样例

    样例输入

    7 12 6 7
    6 1 0 2147483647
    1 7 0 2147483647
    6 2 0 2147483647
    2 7 0 2147483647
    6 3 0 2147483647
    3 7 0 2147483647
    6 4 0 2147483647
    4 7 0 2147483647
    6 5 0 2147483647
    5 7 0 2147483647
    5 1 1 2147483647
    3 4 1 2147483647

    样例输出

    2

    数据范围与提示

    1≤n≤50003,1≤m≤125003 1 leq n leq 50003 , 1leq m leq 1250031n50003,1m125003

    题解:

    注意数据范围,开太小会超时

    #include <bits/stdc++.h>
    const long long inf= 0x3f3f3f3f3f3f3f;
    #define ll long long
    #define MAXN 500003
    using namespace std;
    int n,m;//点数、边数
    int sp,tp;//原点、汇点
    inline bool scan_d(int &num)
    {
        char in;bool IsN=false;
        in=getchar();
        if(in==EOF) return false;
        while(in!='-'&&(in<'0'||in>'9')) in=getchar();
        if(in=='-'){ IsN=true;num=0;}
        else num=in-'0';
        while(in=getchar(),in>='0'&&in<='9'){
            num*=10,num+=in-'0';
        }
        if(IsN) num=-num;
        return true;
    }
    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,ll 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() {
        //freopen("E:\acm1\7.in","r",stdin);
        int s,t;
        scanf("%d%d%d%d",&n,&m,&s,&t);
        init();
        int x,y,low,up;
        for (int i = 0; i <m ; ++i) {
            scan_d(x);scan_d(y);scan_d(low);scan_d(up);
            add(x,y,up-low);
            d[x]-=low;
            d[y]+=low;
        }
        ll sum=0;
        sp=0;tp=n+1;
        for (int i = 1; i <=n ; ++i) {
            if(d[i]>0)
            {
                sum+=d[i];
                add(sp,i,d[i]);
            }
            if(d[i]<0)
            {
                add(i,tp,-d[i]);
            }
        }
        ll ans=0;
        ans+=dinic();
        add(t,s,inf);
        ans+=dinic();
        if(ans==sum)
        {
            printf("%lld
    ",mp[cnt-1].cap);
        } else
            printf("please go home to sleep
    ");
        return 0;
    }
    
    //loj117

     

  • 相关阅读:
    Argparse4j
    Socket通信中的 BeginReceive与EndReceive
    socket 异步通信的一些问题
    static 还是readonly 还是static readonly
    隐藏Android下的虚拟按键
    IIS上架设https网站证书处理备忘
    [转] 移动平台Html5的viewport使用经验
    Air File.load加载问题
    x64位windows 2003 server中“Server 对象 错误 'ASP 0177 : 800700c1' Server.CreateObject 失败”问题
    报 "错误: 无法取消引用int" 的问题解决纪录
  • 原文地址:https://www.cnblogs.com/-xiangyang/p/9788019.html
Copyright © 2011-2022 走看看