【BZOJ3130】费用流(最大流,二分)

题面

Description

Alice和Bob在图论课程上学习了最大流和最小费用最大流的相关知识。

最大流问题:给定一张有向图表示运输网络,一个源点S和一个汇点T,每条边都有最大流量。一个合法的网络流方案必须满足:(1)每条边的实际流量都不超过其最大流量且非负;(2)除了源点S和汇点T之外,对于其余所有点,都满足该点总流入流量等于该点总流出流量;而S点的净流出流量等于T点的净流入流量,这个值也即该网络流方案的总运输量。最大流问题就是对于给定的运输网络,求总运输量最大的网络流方案。

上图表示了一个最大流问题。对于每条边,右边的数代表该边的最大流量,左边的数代表在最优解中,该边的实际流量。需要注意到,一个最大流问题的解可能不是唯一的。 对于一张给定的运输网络,Alice先确定一个最大流,如果有多种解,Alice可以任选一种;之后Bob在每条边上分配单位花费(单位花费必须是非负实数),要求所有边的单位花费之和等于P。总费用等于每一条边的实际流量乘以该边的单位花费。需要注意到,Bob在分配单位花费之前,已经知道Alice所给出的最大流方案。现茌Alice希望总费用尽量小,而Bob希望总费用尽量大。我们想知道,如果两个人都执行最优策略,最大流的值和总费用分别为多少。

Input

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

Output

第一行一个整数,表示最大流的值。

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

Sample Input

3 2 1

1 2 10

2 3 15

Sample Output

10

10.0000

HINT

【样例说明】

对于Alice,最大流的方案是固定的。两条边的实际流量都为10。

对于Bob,给第一条边分配0.5的费用,第二条边分配0.5的费用。总费用

为:100.5+100.5=10。可以证明不存在总费用更大的分配方案。

【数据规模和约定】

对于20%的测试数据:所有有向边的最大流量都是1。

对于100%的测试数据:N < = 100,M < = 1000。

对于l00%的测试数据:所有点的编号在I..N范围内。1 < = 每条边的最大流

量 < = 50000。1 < = P < = 10。给定运输网络中不会有起点和终点相同的边。

题解

第一问不解释了

第二问,很显然的一点

如果是给定费用之和来分配费用

当然是把费用全部分配在流量最大的边上

现在问题便成为了:

在整张网络最大流不变的情况下

流量最大的边的流量最小是多少

最大值最小,考虑二分答案

每次限制最大流量

检查即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define INF 1000000000
#define MAX 500
#define MAXL 5000
inline int read()
{
int x=0,t=1;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Line
{
int v,next;
double w;
}e[MAXL];
struct edge
{
int u,v;
double w;
}p[MAXL];
int h[MAX],cnt;
int ans,S,T,n,m,P;
inline void Add(int u,int v,double w)
{
e[cnt]=(Line){v,h[u],w};
h[u]=cnt++;
e[cnt]=(Line){u,h[v],0};
h[v]=cnt++;
}
int level[MAX];
int cur[MAX];
bool BFS()
{
memset(level,0,sizeof(level));
level[S]=1;
queue<int> Q;
Q.push(S);
while(!Q.empty())
{
int u=Q.front();Q.pop();
for(int i=h[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w&&!level[v])
level[v]=level[u]+1,Q.push(v);
}
}
return level[T];
}
double DFS(int u,double flow)
{
if(flow==0||u==T)return flow;
double ret=0;
for(int &i=cur[u];i!=-1;i=e[i].next)
{
int v=e[i].v;
if(e[i].w&&level[v]==level[u]+1)
{
double dd=DFS(v,min(flow,e[i].w));
flow-=dd;ret+=dd;
e[i].w-=dd;e[i^1].w+=dd;
}
}
return ret;
}
double Dinic()
{
double ret=0;
while(BFS())
{
for(int i=S;i<=T;++i)cur[i]=h[i];
ret+=DFS(S,INF);
}
return ret;
}
void Build(double bb)
{
memset(h,-1,sizeof(h));cnt=0;
for(int i=1;i<=m;++i)
Add(p[i].u,p[i].v,min(p[i].w,bb));
}
int main()
{
n=read();m=read();P=read();
S=1;T=n;
for(int i=1;i<=m;++i)
{
int u=read(),v=read(),w=read();
p[i]=(edge){u,v,w};
}
Build(INF);
double G=Dinic();
printf("%d\n",(int)(G+0.5));
double l=0,r=1e9;
while(r-l>=1e-6)
{
double mid=(l+r)/2;
Build(mid);
if(fabs(Dinic()-G)<=1e-8)r=mid;
else l=mid;
}
printf("%.5lf\n",r*P);
return 0;
}

【BZOJ3130】费用流(最大流,二分)的更多相关文章

  1. poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分, dinic, isap

    poj 2391 Ombrophobic Bovines, 最大流, 拆点, 二分 dinic /* * Author: yew1eb * Created Time: 2014年10月31日 星期五 ...

  2. [源码]ObjectIOStream 对象流 ByteArrayIOStream 数组流 内存流 ZipOutputStream 压缩流

    1.对象流 import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File ...

  3. IO流03_流的分类和概述

    [概述] Java的IO流是实现输入/输出的基础,它可以方便的实现数据的输入/输出操作. Java中把不同的输入/输出源(键盘.文件.网络连接)抽象表述为"流"(Stream). ...

  4. Java基础知识强化之IO流笔记41:字符流缓冲流之复制文本文件案例02(使用 [ newLine() / readLine() ] )(重要)

    1. 使用字符流缓冲流的特殊功能 [ newLine() / readLine() ] 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中  数据源: a.txt -- 读取数据 ...

  5. Java基础知识强化之IO流笔记39:字符流缓冲流之复制文本文件案例01

    1. 字符流缓冲流之复制文本文件案例 需求:把当前项目目录下的a.txt内容复制到当前项目目录下的b.txt中 数据源: a.txt -- 读取数据 -- 字符转换流 -- InputStreamRe ...

  6. Java基础知识强化之IO流笔记38:字符流缓冲流之BufferedWriter / BufferedReader使用

    1. 字符流缓冲流: 字符流为了高效读写,也提供了对应的字符缓冲流. BufferedWriter:字符缓冲输出流 BufferedReader:字符缓冲输入流 2. BufferedWriter使用 ...

  7. JAVA之旅(二十七)——字节流的缓冲区,拷贝mp3,自定义字节流缓冲区,读取键盘录入,转换流InputStreamReader,写入转换流,流操作的规律

    JAVA之旅(二十七)--字节流的缓冲区,拷贝mp3,自定义字节流缓冲区,读取键盘录入,转换流InputStreamReader,写入转换流,流操作的规律 我们继续来聊聊I/O 一.字节流的缓冲区 这 ...

  8. 【Java基础】【21IO(字符流)&字符流其他内容&递归】

    21.01_IO流(字符流FileReader) 1.字符流是什么 字符流是可以直接读写字符的IO流 字符流读取字符, 就要先读取到字节数据, 然后转为字符. 如果要写出字符, 需要把字符转为字节再写 ...

  9. -1-4 java io java流 常用流 分类 File类 文件 字节流 字符流 缓冲流 内存操作流 合并序列流

      File类 •文件和目录路径名的抽象表示形式 构造方法 •public File(String pathname) •public File(String parent,Stringchild) ...

  10. Java转换流、缓冲流、流操作规律整理

    转换流 1.1                OutputStreamWriter类 OutputStreamWriter 是字符流通向字节流的桥梁:可使用指定的字符编码表,将要写入流中的字符编码成字 ...

随机推荐

  1. Centos启动默认打开网络

    Centos打开网络 测试的时候发现网络没有打开,得到图像界面点击网络打开.比较麻烦去搜索了解决方法在此记录下来. 通过 /etc/sysconfig/network-script/, 编辑ifcfg ...

  2. shell脚本实现anisble客户端脚本分发和密钥授权配置

    ##############################Deploy ansible client shell######################## echo "start d ...

  3. Linux中的 awk查找日志中的相关记录

    假设要在 api.log.201707201830 文件中,(此文件的多个字段数据以不可见字符^A(键盘上按下Ctrl+V+A)分隔),要输出第70个字段: awk -F '^A' '{print $ ...

  4. Apollo阿波罗配置中心docker

    前言 在分布式系统中,要改个配置涉及到很多个系统,一个一个改效率低下,吃力不讨好.用配置中心可以解决这个问题.当然配置中心有不少,以下对比的表格是照搬Apollo Wiki的. 功能点 Apollo ...

  5. centos7下安装vsftpd

    安装步骤: 创建ftp目录 cd / mkdir ftpfile 创建指定登陆用户并不让他拥有登陆系统的权限(设置指定登陆shell) useradd ftpuser -d /ftpfile/ -s ...

  6. 2017年StackOverflow上最好的20个Python问题

    1.Python的 .. (点号 点号) 是什么语法? 答案地址:https://stackoverflow.com/questions/43487811/what-is-python-dot-dot ...

  7. php 链接mysql的三种方式对比

    PHP连接Mysql的三种方式: 1.原生的连接方式  原生的连接方式是面向过程的写法 <?php $host = 'localhost'; $database = 'test'; $usern ...

  8. 自定义JpaUtil,快速完成Hql执行逻辑(一)

    这段时间学习Spring Data JPA功能模块.Java持久性API(简称JAP)是类和方法的集合,以海量数据关系映射持久并存储到数据库,这是由Oracle公司提供方案技术.在JAVA社区,深受爱 ...

  9. 第二十一章 Django的分页与cookie

    第二十一章 Django的分页与cookie 第一课 模板 1.模板的继承 在Template目录下新建模板master.html <!DOCTYPE html> <html lan ...

  10. 地牢逃脱 (BFS)

    题意:给定一个 n 行 m 列的地牢,其中 '.' 表示可以通行的位置,'X' 表示不可通行的障碍,牛牛从 (x0 , y0 ) 位置出发,遍历这个地牢,和一般的游戏所不同的是,他每一步只能按照一些指 ...