Coding Contest

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5968    Accepted Submission(s): 1413

Problem Description
A coding contest will be held in this university, in a huge playground. The whole playground would be divided into N blocks, and there would be M directed paths linking these blocks. The i-th path goes from the ui-th block to the vi-th block. Your task is to solve the lunch issue. According to the arrangement, there are sicompetitors in the i-th block. Limited to the size of table, bi bags of lunch including breads, sausages and milk would be put in the i-th block. As a result, some competitors need to move to another block to access lunch. However, the playground is temporary, as a result there would be so many wires on the path.
For the i-th path, the wires have been stabilized at first and the first competitor who walker through it would not break the wires. Since then, however, when a person go through the i - th path, there is a chance of pi to touch
the wires and affect the whole networks. Moreover, to protect these wires, no more than ci competitors are allowed to walk through the i-th path.
Now you need to find a way for all competitors to get their lunch, and minimize the possibility of network crashing.
 
Input
The first line of input contains an integer t which is the number of test cases. Then t test cases follow.
For each test case, the first line consists of two integers N (N ≤ 100) and M (M ≤ 5000). Each of the next N lines contains two integers si and bi (si , bi ≤ 200).
Each of the next M lines contains three integers ui , vi and ci(ci ≤ 100) and a float-point number pi(0 < pi < 1).
It is guaranteed that there is at least one way to let every competitor has lunch.
 
Output
For each turn of each case, output the minimum possibility that the networks would break down. Round it to 2 digits.
 
Sample Input
1
4 4
2 0
0 3
3 0
0 3
1 2 5 0.5
3 2 5 0.5
1 4 5 0.5
3 4 5 0.5
 
Sample Output
0.50
 
Source
 
Recommend
jiangzijing2015
 
 
 /*************************************************************************
> File Name: coding_contest.cpp
> Author: CruelKing
> Mail: 2016586625@qq.com
> Created Time: 2019年09月18日 星期三 10时15分58秒
本题思路: 本题要求使得所有人都找到吃饭的地方且使得网络被破坏的可能性最小,因此
很简单可以看出来是个费用流,但是费用流一般都是统计增广路上的花费的和最小而这里我们
要求的概率为p1 * p2 * p.... * pn最小,因此我们可以想到,可以用对要算的式子取对数就很
容易可以将乘法转换为加法,即我们计算ln(p1) + ln(p2) + ... + ln(pn)然后对结果再取
e的指数(刚算的结果作为指数)很容易就可以求得正解,但是这里我们发现由于我们取得log
底数为e,且概率都是小于1的,因此我们得到费用的值都为负数,这样统计我们得到的是费用
的最大值也即概率的最大值就有错误,所以此时我们可以将问题转换为求解网络不被破坏的
可能行最大的问题,也就是使得(1 - p1) * (1 - p2) * ....* (1 - pn)最大,很容易我们
又可以将其转为log,得到ln(1 - p1) + ln(1 - p2) + ... + ln(1 - pn)最大,同样我们又
可以得到一堆负值,所以我们可以将问题转化非求解原问题的倒数最小的问题,那么很容易
我们就可以得到使得-(ln(1 - p1) + ln(1 - p2) + ... + ln(1 - pn))最小即可,也就是说
我们可以将边的花费设置为 - ln(1 - pi)然后跑费用流就可以了,具体如何建图呢?
我们知道每个结点初始情况可能下有人,而且每个结点还有一个上限,我们首先建立超级源点
s和超级汇点t,对于初始情况下的结点,如果一个结点的s[i] - b[i] > 0那么我们就从s到i
建一条容量为s[i] - b[i]的边,花费为0,如果s[i] - b[i] < 0我们就建一条从i到t的边,
容量为b[i] - s[i],花费为0,又由于第一次踩一根线网络不可能出问题,那我们就拆边,把
原来的边拆为一条容量为1花费为0,另一条容量为c[i] - 1花费为-log(1 - p[i])的边.
ok跑一波费用流.
************************************************************************/ #include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
using namespace std; const int maxn = + , maxm = + , inf = 0x3f3f3f3f;
int n, m, s, t; const double eps = 1e-;
int head[maxn], tot; struct Edge {
int to, flow, cap, next;
double cost;
} edge[maxm << ]; void init() {
memset(head, -, sizeof head);
tot = ;
} void addedge(int u, int v, int cap, double cost) {
edge[tot].to = v; edge[tot].flow = ; edge[tot].cap = cap; edge[tot].cost = cost;
edge[tot].next = head[u]; head[u] = tot ++;
edge[tot].to = u; edge[tot].flow = ; edge[tot].cap = ; edge[tot].cost = -cost;
edge[tot].next = head[v]; head[v] = tot ++;
} int pre[maxn];
double dis[maxn];
bool vis[maxn];
int cnt[maxn]; bool spfa() {
queue<int> que;
for(int i = ; i <= n + ; i ++) {
dis[i] = inf;
vis[i] = false;
pre[i] = -;
cnt[i] = ;
}
cnt[s] = ;
dis[s] = 0.0;
vis[s] = true;
que.push(s);
while(!que.empty()) {
int u = que.front(); que.pop(); vis[u] = false;
for(int i = head[u]; ~i; 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]) {
cnt[v] ++;
vis[v] = true;
que.push(v);
if(cnt[v] > n) return false;
}
}
}
}
if(pre[t] == -) return false;
else return true;
} void mincostmxflow (double &ans) {
while(spfa()) {
int Min = inf;
for(int i = pre[t]; ~i; i = pre[edge[i ^ ].to]) {
if(Min > edge[i].cap - edge[i].flow) Min = edge[i].cap - edge[i].flow;
}
for(int i = pre[t]; ~i; i = pre[edge[i ^ ].to]) {
edge[i].flow += Min;
edge[i ^ ].flow -= Min;
ans += edge[i].cost * Min;
}
}
} int main() {
int _case, si, bi, u, v, c;
double pi;
scanf("%d", &_case);
while(_case --) {
init();
scanf("%d %d", &n, &m);
s = , t = n + ;
for(int i = ; i <= n; i ++) {
scanf("%d %d", &si, &bi);
if(si > bi) addedge(s, i, si - bi, 0.0);
else if(si < bi) addedge(i, t, bi - si, 0.0);
}
for(int i = ; i < m; i ++) {
scanf("%d %d %d %lf", &u, &v, &c, &pi);
if(c > ) addedge(u, v, , 0.0);
if(c > ) addedge(u, v, c - , -log2( - pi));
}
double ans = ;
mincostmxflow(ans);
printf("%.2f\n", 1.0 - pow(, -ans));
}
return ;
}
 

2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)的更多相关文章

  1. HDU5988 Coding Contest(费用流)

    2016青岛现场赛的一题,由于第一次走过不会产生影响,需要拆点,不过比赛时没想到,此外还有许多细节要注意,如要加eps,时间卡得较紧要注意细节优化等 #include <iostream> ...

  2. UVALive - 7740 Coding Contest 2016 青岛区域赛 (费用流)

    题意:每个点i有\(s_i\)个人和\(b_i\)份食物,每个人都要找到一份食物.现在有M条有向边,从点i到点j,容量为c,第一次走过不要紧,从第二次开始就要承担\(p(0<p<1)\)的 ...

  3. HDU5988 - 2016icpc青岛 - G - Coding Contest 费用流(利用对数化乘为加

    HDU5988 题意: 有n个区域,每个区域有s个人,b份饭.现在告诉你每个区域间的有向路径,每条路有容量和损坏路径的概率.问如何走可以使得路径不被破坏的概率最小.第一个人走某条道路是百分百不会损坏道 ...

  4. Coding Contest(费用流变形题,double)

    Coding Contest http://acm.hdu.edu.cn/showproblem.php?pid=5988 Time Limit: 2000/1000 MS (Java/Others) ...

  5. hdu-5988 Coding Contest(费用流)

    题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Ot ...

  6. HDU 5988 Coding Contest(费用流+浮点数)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988 题目大意: 给定n个点,m条有向边,每个点是一个吃饭的地方,每个人一盒饭.每个点有S个人,有B盒 ...

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

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

  8. ACM/ICPC2016 青岛区域赛

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

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

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

随机推荐

  1. postman批量调用接口并发测试

    本文出自:https://www.cnblogs.com/2186009311CFF/p/11425913.html 接口测试在开发中很容易遇到,下面是请教别人学会的并发测试,希望能帮到需要用到的你, ...

  2. react样式

    https://www.jianshu.com/p/711c596571d6(copy)

  3. Luogu P4550 收集邮票

    题目链接:Click here Solution: 本题直接推价格似乎很难,考虑先从购买次数入手 设购买次数\(g(i)\)为当前有\(i\)种不同的邮票,要买到\(n\)种的期望购买次数 可以由期望 ...

  4. [UPC10525]:Dove打扑克(暴力+模拟)

    题目描述 $Dove$和$Cicada$是好朋友,他们经常在一起打扑克来消遣时光,但是他们打的扑克有不同的玩法. 最开始时,牌桌上会有$n$个牌堆,每个牌堆有且仅有一张牌,第$i$个牌堆里里里那个扑克 ...

  5. 利用Lucene.net搜索引擎进行多条件搜索的做法

    利用Lucene.net搜索引擎进行多条件搜索的做法 2018年01月09日 ⁄ 搜索技术 ⁄ 共 613字 ⁄ 字号 小 中 大 ⁄ 评论关闭 利用Lucene.net搜索引擎进行多条件搜索的做法 ...

  6. 微信小程序 API 数据缓存

    微信小程序 数据缓存 (类似于 cookie) wx.setStorage() 将数据存储在本地缓存中制定的 key 中.会覆盖掉原来该 key 对应的内容,数据存储生命周期跟小程序本身一致,即除用户 ...

  7. 一、基础篇--1.1Java基础-自定义注解的场景及实现

    自定义注解使用场景: 类属性自动赋值,例如对上下文.传入参数等赋值 验证对象属性完整性,例如,对参数的校验 代替配置文件功能,像spring基于注解的配置 可以生成文档,例如java 最早提供的注解. ...

  8. eclipse 4.32 安装 gradle

    更新网址  http://dist.springsource.com/release/TOOLS/gradle

  9. 记一次 Vue 组件内存泄漏的坑

    概述 最近在开发 Vue 项目的时候遇到了内存泄漏问题,记录下来,供以后开发时参考,相信对其他人也有用. 背景 背景是需要用 three.min.js 和 vanta.net.min.js 给首页加上 ...

  10. jest 提示 Unexpected identifier 的解决方案

    概述 今天在玩 jest 的时候,发现用 import 就会报 Unexpected identifier 的错误.查了很久的资料,最后终于解决了. 参考资料:Jest tests can't pro ...