zoukankan      html  css  js  c++  java
  • ZOJ 3496 Assignment | 二分+有上下界网络流

    题目:

    http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3496

    大概意思:给你一个网络,有源汇,在保证最大流的情况下求下面两个问题答案

    1.所有边中流量最大的边流量最小

    2.所有边中流量最小的边流量最大


    题解:

    De了一下午啊啊,之前学的上下界网络流有问题!

    对于问题一,我们二分最大流量,每次建图跑最大流,看是不是和之前一样即可

    对于问题二,我们同样二分答案lim,这样每条边满足流量限制w[i]∈[lim,c[i]]

    这样建图跑有源汇最大流即可.

    下面是坑点

    之前写的有源汇最大流都是先跑可行流然后把超级源和超级汇删掉再跑,答案还得加加减减,但是就是Wa

    后来发现其实并没有那么难,在可行流的残余网络直接再跑一边最大流就是答案

    感性证明如下:

    因为如果可行的话超级源的所有出边都满流,这样算最大流的时候只会算到t->s的反边上,又因为原来的可行流就在这条边上,这样直接就能算出答案

    别忘了输出答案*p

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    typedef long long ll;
    #define N 505
    #define M 400005
    #define INF 0x3f3f3f3f
    using namespace std;
    ll Case,n,m,t,s,P,ans1,ans2,S,T,ecnt,Maxflow,l,r,u[M],v[M],c[M],mid,Maxc,lim;
    ll head[N],lev[N],cur[N],du[N];
    queue <ll> q;
    struct adj
    {
        ll nxt,v,w;
    } e[M];
    ll read()
    {
        ll ret=0,neg=1;
        char j=getchar();
        for (; j>'9' || j<'0'; j=getchar())
            if (j=='-') neg=-1;
        for (; j>='0' && j<='9'; j=getchar())
            ret=ret*10+j-'0';
        return ret*neg;
    }
    void add(ll u,ll v,ll w)
    {
        e[++ecnt].v=v;e[ecnt].w=w;e[ecnt].nxt=head[u];head[u]=ecnt;
        e[++ecnt].v=u;e[ecnt].w=0;e[ecnt].nxt=head[v];head[v]=ecnt;
    }
    void init()
    {
        ecnt=1;
        memset(head,0,sizeof(head));
    }
    bool Bfs()
    {
        while (!q.empty()) q.pop();
        for (ll i=1; i<=lim; i++)
            cur[i]=head[i],lev[i]=-1;
        q.push(S),lev[S]=1;
        while (!q.empty())
        {
            ll u=q.front();
            q.pop();
            for (ll i=head[u],v; i; i=e[i].nxt)
                if (lev[v=e[i].v]==-1 && e[i].w>0)
                {
                    q.push(v),lev[v]=lev[u]+1;
                    if (v==T) return 1;
                }
        }
        return 0;
    }
    ll Dfs(ll u,ll flow)
    {
        if (u==T) return flow;
        ll ret=0,delta;
        for (ll &i=cur[u],v; i; i=e[i].nxt)
            if (e[i].w>0 && lev[v=e[i].v]==lev[u]+1)
            {
                delta=Dfs(v,min(e[i].w,flow-ret));
                if (delta)
                {
                    e[i].w-=delta;
                    e[i^1].w+=delta;
                    ret+=delta;
                    if (ret==flow) break;
                }
            }
        return ret;
    }
    ll getG(ll lim)
    {
        ll sum=0,tmp=0;
        init();
        add(t,s,INF);S=n+1,T=n+2;
        memset(du,0,sizeof(du));
        for (ll i=1; i<=m; i++)
            if (c[i]-lim<0) return -1;
            else add(u[i],v[i],c[i]-lim),du[u[i]]-=lim,du[v[i]]+=lim;
        for (ll i=1; i<=n; i++)
        {
            if (du[i]>0) add(S,i,du[i]),sum+=du[i];
            if (du[i]<0) add(i,T,-du[i]);
        }
        while (Bfs()) tmp+=Dfs(S,INF);
        if (tmp!=sum) return -1;
        tmp=0;S=s;T=t;
        while (Bfs()) tmp+=Dfs(S,INF);
        return tmp;
    }
    int main()
    {
        Case=read();
        while (Case--)
        {
            n=read(),m=read(),s=read(),t=read(),P=read();
            init();
            S=++s;T=++t;
            Maxflow=Maxc=l=0;
            lim=n+2;
            for (ll i=1; i<=m; i++)
                u[i]=read(),v[i]=read(),c[i]=read(),add(++u[i],++v[i],c[i]),r=Maxc=max(Maxc,c[i]);
            while (Bfs()) Maxflow+=Dfs(S,INF);
            while (l<r)
            {
                init();
                ll mid=l+r>>1,tmp=0;
                for (ll i=1; i<=m; i++) add(u[i],v[i],min(c[i],mid));
                while (Bfs()) tmp+=Dfs(S,INF);
                if (tmp==Maxflow) r=mid;
                else l=mid+1;
            }
            ans1=l;l=0;r=Maxc;
            while (l<r)
            {
                ll mid=l+r+1>>1,tmp=0;
                if (getG(mid)==Maxflow) l=mid;
                else r=mid-1;
            }
            ans2=l;
            printf("%lld %lld
    ",1ll*ans1*P,1ll*ans2*P);
        }
        return 0;
    }
  • 相关阅读:
    flutter之正则
    Flutter:Slivers大家族,让滑动视图的组合变得很简单!
    flutter之添加阴影
    flutter之https://www.jianshu.com/p/594a327267dc
    mac os下vscode快捷键
    detached HEAD解决办法
    flutter如何使用配置文件pubspec.yaml(位于项目根目录)来管理第三方依赖包
    flutter Route路由基本用法
    更新操作 关于json字符串的拼接、json字符串与json对象之间的转换
    做筛选遍历时遇到的json字符串、json对象、json数组 三者之间的转换问题
  • 原文地址:https://www.cnblogs.com/mrsheep/p/8215489.html
Copyright © 2011-2022 走看看