【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\n" , flow = solve(1e9));
    while(cnt -- )
    {
        mid = (l + r) / 2;
        if(solve(mid) == flow) r = mid;
        else l = mid;
    }
    printf("%.4lf\n" , r * p);
    return 0;
}

原文地址:https://www.cnblogs.com/GXZlegend/p/8323561.html

时间: 2024-10-18 05:56:45

【bzoj3130】[Sdoi2013]费用流 二分+网络流最大流的相关文章

POJ 2455 Secret Milking Machine(搜索-二分,网络流-最大流)

Secret Milking Machine Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9658   Accepted: 2859 Description Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within

【bzoj1822】[JSOI2010]Frozen Nova 冷冻波 计算几何+二分+网络流最大流

题目描述 WJJ喜欢“魔兽争霸”这个游戏.在游戏中,巫妖是一种强大的英雄,它的技能Frozen Nova每次可以杀死一个小精灵.我们认为,巫妖和小精灵都可以看成是平面上的点. 当巫妖和小精灵之间的直线距离不超过R,且巫妖看到小精灵的视线没有被树木阻挡(也就是说,巫妖和小精灵的连线与任何树木都没有公共点)的话,巫妖就可以瞬间杀灭一个小精灵. 在森林里有N个巫妖,每个巫妖释放Frozen Nova之后,都需要等待一段时间,才能再次施放.不同的巫妖有不同的等待时间和施法范围,但相同的是,每次施放都可以

【bzoj1733】[Usaco2005 feb]Secret Milking Machine 神秘的挤奶机 二分+网络流最大流

题目描述 Farmer John is constructing a new milking machine and wishes to keep it secret as long as possible. He has hidden in it deep within his farm and needs to be able to get to the machine without being detected. He must make a total of T (1 <= T <=

BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]

3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 960  Solved: 505[Submit][Status][Discuss] Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都不超

BZOJ3130 SDOI2013 费用流 二分法+网络流

题意:给定一张图,求:1.最大流  2.最大流方案中,流量最大的一条边 题解: 第一问裸题 第二问显然Bob要把所有的费用加在流量最大的边上,因此我们二分最长边,每条边的流量改为min{二分出的最大流量,当前边的流量},跑最大流检验. 注意可以是实数流量,比如说: <1,2,3> <3,2,3> <2,4,2> <2,5,2> <2,6,1> 那么加在<1,2>和<3,2>上的流量用2.5最优 #include <q

Luogu P3305 [SDOI2013]费用流 二分 网络流

题目链接 \(Click\) \(Here\) 非常有趣的一个题目. 关键结论:所有的单位费用应该被分配在流量最大的边上. 即:在保证最大流的前提下,使最大流量最小.这里我们采用二分的方法,每次判断让所有边的流量\(<=mid\)时是否依然有最大流,求得最小的最大流量\(*p\)即可. 为什么会有实数流量呢?其实我也不懂,不过这也造成这个题目需要把流量改成\(double\),有很多细节需要小心谨慎... #include <bits/stdc++.h> using namespace

【二分答案】【最大流】bzoj3130 [Sdoi2013]费用流

二分最大的边的cap,记作Lim. 把所有的边的cap设为min(Lim,cap[i]). Bob一定会把单位费用加到最大边上. #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<cmath> using namespace std; #define EPS 0.000001 #define N 101 #define INF 21474

Bzoj3130 [Sdoi2013]费用流

Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1041  Solved: 536 Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.    最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都不超过其最大流量且非负:(2)除了源点S和汇点T之外,对于其余所有点,都满足该点总流入流量等

BZOJ 3130: [Sdoi2013]费用流 网络流+二分

3130: [Sdoi2013]费用流 Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 1230  Solved: 598[Submit][Status][Discuss] Description Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识.     最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量.一个合法的网络流方案必须满足:(1)每条边的实际流量都