zoukankan      html  css  js  c++  java
  • 【bzoj3130】[Sdoi2013]费用流 二分+网络流最大流

    题目描述

    Alice和Bob做游戏,给出一张有向图表示运输网络,Alice先给Bob一种最大流方案,然后Bob在所有边上分配总和等于P的非负费用。Alice希望总费用尽量小,而Bob希望总费用尽量大。求两人都采取最优策略的情况下最大流及总费用。

    输入

    第一行三个整数N,M,P。N表示给定运输网络中节点的数量,M表示有向边的数量,P的含义见问题描述部分。为了简化问题,我们假设源点S是点1,汇点T是点N。
    接下来M行,每行三个整数A,B,C,表示有一条从点A到点B的有向边,其最大流量是C。

    输出

    第一行一个整数,表示最大流的值。
    第二行一个实数,表示总费用。建议选手输出四位以上小数。

    样例输入

    3 2 1
    1 2 10
    2 3 15

    样例输出

    10
    10.000


    题解

    二分+网络流最大流

    显然对于Alice给出的一种方案,Bob只需要在流量最大的边上设置费用P,其它边费用为0,即可使费用最大。

    所以Alice要使费用尽量小,就需要使流量最大的边的流量最小。

    先跑一遍最大流得出第一问的答案。然后二分最大流量,对于一条边,将其容量设置为 min(原图中流量,mid) ,跑最大流,如果最大流等于原图的最大流则可行,否则不可行。

    最后的答案就是mid*P。

    我才不会告诉你们第二问puts("nan")可过呢

    #include <queue>
    #include <cstdio>
    #include <cstring>
    #define N 110
    #define M 2010
    using namespace std;
    queue<int> q;
    int m , px[M] , py[M] , head[N] , to[M] , next[M] , cnt , s , t , dis[N];
    double pz[M] , val[M];
    inline void add(int x , int y , double z)
    {
        to[++cnt] = y , val[cnt] = z , next[cnt] = head[x] , head[x] = cnt;
        to[++cnt] = x , val[cnt] = 0 , next[cnt] = head[y] , head[y] = cnt;
    }
    bool bfs()
    {
        int x , i;
        memset(dis , 0 , sizeof(dis));
        while(!q.empty()) q.pop();
        dis[s] = 1 , q.push(s);
        while(!q.empty())
        {
            x = q.front() , q.pop();
            for(i = head[x] ; i ; i = next[i])
            {
                if(val[i] && !dis[to[i]])
                {
                    dis[to[i]] = dis[x] + 1;
                    if(to[i] == t) return 1;
                    q.push(to[i]);
                }
            }
        }
        return 0;
    }
    double dinic(int x , double low)
    {
        if(x == t) return low;
        double temp = low , k;
        int i;
        for(i = head[x] ; i ; i = next[i])
        {
            if(val[i] && dis[to[i]] == dis[x] + 1)
            {
                k = dinic(to[i] , min(temp , val[i]));
                if(!k) dis[to[i]] = 0;
                val[i] -= k , val[i ^ 1] += k;
                if(!(temp -= k)) break;
            }
        }
        return low - temp;
    }
    double solve(double mid)
    {
        int i;
        double ans = 0;
        memset(head , 0 , sizeof(head)) , cnt = 1;
        for(i = 1 ; i <= m ; i ++ ) add(px[i] , py[i] , min(pz[i] , mid));
        while(bfs()) ans += dinic(s , 1e9);
        return ans;
    }
    int main()
    {
        int n , i , cnt = 50;
        double l = 0 , r = 1e9 , mid , flow , p;
        scanf("%d%d%lf" , &n , &m , &p) , s = 1 , t = n;
        for(i = 1 ; i <= m ; i ++ ) scanf("%d%d%lf" , &px[i] , &py[i] , &pz[i]);
        printf("%.0lf
    " , flow = solve(1e9));
        while(cnt -- )
        {
            mid = (l + r) / 2;
            if(solve(mid) == flow) r = mid;
            else l = mid;
        }
        printf("%.4lf
    " , r * p);
        return 0;
    }
    

     

  • 相关阅读:
    Maven导包失败三种解决方案-Could not transfer artifact
    MySQL远程登录赋权操作各命令的意思
    大数据技术与应用课堂测试01
    软件体系架构课堂测试01
    设计模式复习笔记23
    设计模式复习笔记22
    设计模式复习笔记21
    设计模式复习笔记20
    设计模式复习笔记19
    设计模式复习笔记18
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8323561.html
Copyright © 2011-2022 走看看