2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)
Coding Contest
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 5968 Accepted Submission(s): 1413
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.
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.
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
/*************************************************************************
> 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(费用流 + 概率计算转换为加法计算)的更多相关文章
- HDU5988 Coding Contest(费用流)
2016青岛现场赛的一题,由于第一次走过不会产生影响,需要拆点,不过比赛时没想到,此外还有许多细节要注意,如要加eps,时间卡得较紧要注意细节优化等 #include <iostream> ...
- UVALive - 7740 Coding Contest 2016 青岛区域赛 (费用流)
题意:每个点i有\(s_i\)个人和\(b_i\)份食物,每个人都要找到一份食物.现在有M条有向边,从点i到点j,容量为c,第一次走过不要紧,从第二次开始就要承担\(p(0<p<1)\)的 ...
- HDU5988 - 2016icpc青岛 - G - Coding Contest 费用流(利用对数化乘为加
HDU5988 题意: 有n个区域,每个区域有s个人,b份饭.现在告诉你每个区域间的有向路径,每条路有容量和损坏路径的概率.问如何走可以使得路径不被破坏的概率最小.第一个人走某条道路是百分百不会损坏道 ...
- Coding Contest(费用流变形题,double)
Coding Contest http://acm.hdu.edu.cn/showproblem.php?pid=5988 Time Limit: 2000/1000 MS (Java/Others) ...
- hdu-5988 Coding Contest(费用流)
题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
- HDU 5988 Coding Contest(费用流+浮点数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5988 题目大意: 给定n个点,m条有向边,每个点是一个吃饭的地方,每个人一盒饭.每个点有S个人,有B盒 ...
- HDU 5880 Family View (2016 青岛网络赛 C题,AC自动机)
题目链接 2016 青岛网络赛 Problem C 题意 给出一些敏感词,和一篇文章.现在要屏蔽这篇文章中所有出现过的敏感词,屏蔽掉的用$'*'$表示. 建立$AC$自动机,查询的时候沿着$fa ...
- ACM/ICPC2016 青岛区域赛
A(hdu5982).(模拟) 题意:输入n对数,将每对数相乘并相加 分析:模拟 B(hdu5983).(模拟) 题意:给你一个二阶魔方,问能否通过一次旋转使得给定魔方的每个面颜色相同 分析:模拟 C ...
- ACM-ICPC 2016亚洲区域赛(沈阳站)游记(滚粗记)
首发于QQ空间和知乎,我在这里也更一下. 前言 以前高中搞竞赛的时候,经常看到神犇出去比赛或者训练之后写游记什么的,感觉萌萌哒.但是由于太弱,就没什么心情好写.现在虽然还是很弱,但是抱着享受的心情 ...
随机推荐
- SQL中INEXISTS和IN 的区别和联系
SET NOCOUNT ON , SET NOCOUNT OFF当 SET NOCOUNT 为 ON 时,不返回计数(表示受 Transact-SQL 语句影响的行数).当 SET NOCOUNT 为 ...
- 设计模式Design Pattern(4) -- 访问者模式
什么是访问者模式? 一个对象有稳定的数据结构,却为不同的访问者提供不同的数据操作,对象提供接收访问者的方法,从而保证数据结构的稳定性和操作的多样性.也可以理解为,封装对象的操作方法,达到不改变对象数据 ...
- shiro框架学习-8-shiro缓存
1. shiro进行认证授权时会查询数据库获取用户角色权限信息,每次登录都会去查询,这样对性能会又影响.可以设置缓存,查询时先去缓存中查找,缓存中没有再去数据库查询. 从shiro的架构图中可以看到有 ...
- CDOJ 1069 秋实大哥去打工 单调栈 下标处理
E - 秋实大哥去打工 Time Limit:1000MS Memory Limit:65535KB 64bit IO Format:%lld & %llu Submit St ...
- Shell中Bash的基本功能(二)
1 历史命令 1)历史命令的查看[root@localhost ~]# history [选项] [历史命令保存文件]选项:-c: 清空历史命令-w: 把缓存中的历史命令写入历史命令保存文件.如果不手 ...
- cvpr 2019 workshop&oral session
1. Verification and Certification of Neural Networks神经网络的验证与认证 2. Automated Analysis of Marine Video ...
- NABCD分析——生活日历
N(Need)需求 本软件的主体为日历.如今人们的生活趋于现代化,大家主要通过手机来查看日期,但我们每一天都有想要做或未完成的事情,也存在对自己有特殊意义的日子.每天人们都会有或大或小的支出与收入,想 ...
- [BZOJ2111]:[ZJOI2010]Perm 排列计数(组合数学)
题目传送门 题目描述 称一个1,2,...,N的排列${P}_{1}$,${P}_{2}$,...,${P}_{N}$是Magic的,当且仅当2≤i≤N时,${P}_{i}$>${P}_{\fr ...
- Java并发编程的艺术笔记(三)——Thread.join()
t.join()方法只会使主线程进入等待池并等待t线程执行完毕后才会被唤醒.并不影响同一时刻处在运行状态的其他线程.它能够使得t.join()中的t优先执行,当t执行完后才会执行其他线程.能够使得线程 ...
- socket的补充