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. day_14 匿名函数与内置函数连用 作业题

    ''' 要求: 从文件中取出每一条记录放入列表中,列表的每个元素都是` {'name':'egon','sex':'male','age':18,'salary':3000}`的形式 ''' all_ ...

  2. 通过源码安装PostgresSQL

    通过源码安装PostgresSQL 1.1 下载源码包环境: Centos6.8 64位 yum -y install bison flex readline-devel zlib-devel yum ...

  3. 15. ClustrixDB 管理数据分布

    本节使用的关键术语: Relation — ClustrixDB中的每个表都被称为“关系”. Representation — 在ClustrixDB中,每个索引都称为一个“Representatio ...

  4. postgres select TOP X in group 查询每个组的前几名

    参考: https://stackoverflow.com/questions/27415706/postgresql-select-top-three-in-each-group http://ch ...

  5. Tire树简介

    又称单词查找树,Trie树,是一种树形结构,是一种哈希树的变种. 典型应用:用于统计,排序和保存大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计. 它的优点是:利用字符串的公共 ...

  6. Luogu P5468 [NOI2019]回家路线 (斜率优化、DP)

    题目链接: (luogu) https://www.luogu.org/problemnew/show/P5468 题解: 爆long long毁一生 我太菜了,这题这么简单考场上居然没想到正解-- ...

  7. [CF1101F]Trucks and Cities:分治优化决策单调性

    分析 好像是有一个叫这个名字的算法,链接. 令\(f[i][j][k]\)表示一辆每公里耗油量为\(1\)的货车从\(i\)到\(j\)中途加\(k\)次油最小的油箱容量.枚举所有的起点和中途加油的次 ...

  8. @清晰掉 makefile

    参阅: http://www.cnblogs.com/wang_yb/p/3990952.html

  9. socket基本概念

    1.socket 是什么? 在计算机通信领域,socket 被翻译为“套接字”,它是计算机之间进行通信的一种约定或一种方式.通过 socket 这种约定,一台计算机可以接收其他计算机的数据,也可以向其 ...

  10. C# 读取Excel中的数据到DataTable中

    原文地址:http://www.open-open.com/code/view/1420029490093 public DataTable ExcelToDS(string Path) { stri ...