题意:每个点i有\(s_i\)个人和\(b_i\)份食物,每个人都要找到一份食物.现在有M条有向边,从点i到点j,容量为c,第一次走过不要紧,从第二次开始就要承担\(p(0<p<1)\)的道路损坏的风险.题目保证每个人都能拿到食物,求这个风险的最小值.

分析:建立源点S和汇点T.从S到点i建容量为\(s_i\),费用为0的边;从点i到T建容量为\(b_i\),费用为0的边.

风险的最小值可以转化为求安全达成目标的. 则\(ans = \prod (1-p_i)^{k_i}\),

对ans取对数,\(log(ans) = \sum k_i*log(1-p_i)\).因为需要求这个值最大,所以费用需要取反.

因为第一次走没有风险,可以将这条容量为1的边分离出来,若容量还有剩余则建容量为\(c-1\),费用为\(-log(1-p)\)的边.

跑一遍费用流,费用取反再还原之后就是最大的安全通过的概率,1减去这个概率就是最小的风险.

#include<bits/stdc++.h>
using namespace std;
#define eps 1e-7
const int MAXN = 10005;
const int MAXM = 100005;
const int INF = 0x3f3f3f3f;
struct Edge{
int to, next, cap, flow;
double cost;
} edge[MAXM];
int head[MAXN], tot;
int pre[MAXN];
double dis[MAXN];
bool vis[MAXN];
int N;
void init(int n)
{
N = n;
tot = 0;
memset(head, -1, sizeof(head));
} void AddEdge(int u, int v, int cap, double cost)
{
edge[tot] = (Edge){v,head[u],cap,0,cost};
head[u] = tot++;
edge[tot] = (Edge){u,head[v],0,0,-cost};
head[v] = tot++;
} bool spfa(int s, int t){
queue<int> q;
for (int i = 0; i <= N; i++){
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0;
vis[s] = true;
q.push(s);
while (!q.empty()){
int u = q.front();
q.pop();
vis[u] = false;
for (int i = head[u]; i != -1; i = edge[i].next){
int v = edge[i].to; if (edge[i].cap > edge[i].flow && dis[v] - (dis[u] + edge[i].cost)> eps){
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if (!vis[v]){
vis[v] = true;
q.push(v);
}
}
}
}
if (pre[t] == -1) return false;
else return true;
} int minCostMaxflow(int s, int t, double &cost){
int flow = 0;
cost = 0;
while (spfa(s, t)){
int Min = INF;
for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]){
if (Min > edge[i].cap - edge[i].flow)
Min = edge[i].cap - edge[i].flow;
}
for (int i = pre[t]; i != -1; i = pre[edge[i ^ 1].to]){
edge[i].flow += Min;
edge[i ^ 1].flow -= Min;
cost += edge[i].cost * Min;
}
flow += Min;
}
return flow;
} int have[MAXN];
int need[MAXN]; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
scanf("%d",&T);
while(T--){
int n,m;
scanf("%d %d",&n,&m);
init(n+2);
int u,v; double w;
int s= 0, t = n+1;
for(int i=1 ; i<=n; ++i){
scanf("%d %d", &need[i], &have[i]);
}
for(int i=1;i<=n;++i){
AddEdge(s,i,need[i],0);
AddEdge(i,t,have[i],0);
} int c;
double p;
for(int i=1;i<=m;++i){
scanf("%d %d %d %lf",&u, &v, &c, &p);
if(c >= 1) AddEdge(u,v,1,0.0);
if(c > 1) AddEdge(u,v,c-1,-log2(1.0-p));
}
double cost = 0.0;
minCostMaxflow(s,t,cost);
//cout<<cost<<endl;
printf("%.2f\n",1.0-pow(2.0,-cost));
}
return 0;
}

UVALive - 7740 Coding Contest 2016 青岛区域赛 (费用流)的更多相关文章

  1. 2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)

    Coding Contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  2. HDU 5880 Family View (2016 青岛网络赛 C题,AC自动机)

    题目链接  2016 青岛网络赛  Problem C 题意  给出一些敏感词,和一篇文章.现在要屏蔽这篇文章中所有出现过的敏感词,屏蔽掉的用$'*'$表示. 建立$AC$自动机,查询的时候沿着$fa ...

  3. ACM-ICPC 2016亚洲区域赛(沈阳站)游记(滚粗记)

    首发于QQ空间和知乎,我在这里也更一下.   前言 以前高中搞竞赛的时候,经常看到神犇出去比赛或者训练之后写游记什么的,感觉萌萌哒.但是由于太弱,就没什么心情好写.现在虽然还是很弱,但是抱着享受的心情 ...

  4. ACM/ICPC2016 青岛区域赛

    A(hdu5982).(模拟) 题意:输入n对数,将每对数相乘并相加 分析:模拟 B(hdu5983).(模拟) 题意:给你一个二阶魔方,问能否通过一次旋转使得给定魔方的每个面颜色相同 分析:模拟 C ...

  5. 2019.6.1 模拟赛——[ 费用流 ][ 数位DP ][ 计算几何 ]

    第一题:http://codeforces.com/contest/1061/problem/E 把点集分成不相交的,然后跑费用流即可.然而错了一个点. #include<cstdio> ...

  6. 2016 年 ACM/ICPC 青岛区域赛 Problem C Pocky

    昨晚乱入学弟的训练赛,想了一下这个题.推导的过程中,加深了对公理化的概率论理解.$\newcommand{\d}{\mathop{}\!\mathrm{d}}$ 解法一 考虑 $ d < L$ ...

  7. The 2014 ACM-ICPC Asia Mudanjiang Regional Contest(2014牡丹江区域赛)

    The 2014 ACM-ICPC Asia Mudanjiang Regional Contest 题目链接 没去现场.做的网络同步赛.感觉还能够,搞了6题 A:这是签到题,对于A堆除掉.假设没剩余 ...

  8. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  9. HDU - 5878 2016青岛网络赛 I Count Two Three(打表+二分)

    I Count Two Three 31.1% 1000ms 32768K   I will show you the most popular board game in the Shanghai ...

随机推荐

  1. Logstash zabbix 插件

    zabbix 监控 logstash 安装社区扩展包wget http://download.elasticsearch.org/logstash/logstash/logstash-contrib- ...

  2. 【代码备份】NLM插值

    文件路径: main.m: %% 测试函数 clc,clear all,close all; %输入的原始小图 ima_ori=double(imread('F:\Users\****n\Docume ...

  3. web.xml 中 classpath 写法说明

    简单理解,classpath就是代表  /WEB-INF /classes/  这个路径(如果不理解该路径,就把一个web工程发布为war包,然后用winrar查看其包内路径就理解啦) 常用的场景: ...

  4. Python 读取json文件

    创建json文件: { "fontFamily": "微软雅黑", "fontSize": 12, "BaseSettings&q ...

  5. __del__()

    __del__() 是类的内置函数,用于定义在脚本退出之前要执行的代码,因为有这个特性,通常被用来在脚本退出前关闭文件.关闭数据库连接.关闭网络连接等操作 [root@localhost ~]$ ca ...

  6. Android开源项目分类汇总【畜生级别】

    From :http://blog.csdn.net/forlong401/article/details/25459403?c=6c4cd677a617db4655988e41ee081691#t7 ...

  7. java的list集合如何根据对象中的某个字段排序?

    转自:http://blog.csdn.net/wangjuan_01/article/details/51351633 List集合按某个字段排序 package wjtest_01; import ...

  8. angular4 常用pipe管道

    angular中的pipe是用来对输入的数据进行处理,如大小写转换.数值和日期格式化等. 常用的pipe有 1. 大小写转换 <p>{{str | uppercase}}</p> ...

  9. DocumentFragment 不支持 innerHTML

    在需要多次使用 innerHTML 的地方,一般是推荐用 DocumentFragment 来缓存,最后一次性插入 body,从而减少浏览器的渲染,提高性能,不过最近也发现一个 bug: Docume ...

  10. 170425、centos安装mysql5.6数据库

    # rpm -qa | grep mysql ## 查看该操作系统上是否已经安装了 mysql 数据库, 有的话,可以通过 rpm -e 命令 或者 rpm -e --nodeps 命令来卸载掉 # ...