HDU 5988 Coding Contest (最小费用流)
来源:互联网 发布:蓝月单机翅膀升阶数据 编辑:程序博客网 时间:2024/05/16 09:35
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 si competitors 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
14 42 00 33 00 31 2 5 0.53 2 5 0.51 4 5 0.53 4 5 0.5
Sample Output
0.50
题意
有
思路
最小费用流的基础题。
首先我们可以让某个区域的人得到当前他所在区域的某个食物,然后原图转化为每一个点存在一些人或者存在一些食物,要求碰到电线的最小概率也就是不碰到电线的最大概率。
假设碰到某条电线的概率为
我们知道
随后从源点向每一个人所在的节点连有向边,每一个食物所在的节点向汇点连有向边,找最小费用即可。
PS: 这道题目卡常好严重,貌似 1000ms 的题目 998ms 过的。
So ,如果 TLE 可以考虑再提交一下。
AC 代码
#include<bits/stdc++.h>using namespace std;const int maxn = 105;const int maxm = 21000;const int INF = 2e9;const double eps = 1e-8;struct edge{ int to; //边终点 int next; //下一个兄弟位置 int cap; //容量 int flow; //流量 double cost; //费用} edge[maxm];int head[maxn],tol;int pre[maxn];double dis[maxn];int N; //节点总个数bool vis[maxn];int person[maxn],thing[maxn];void init(int n){ N=n; tol=0; memset(head,-1,sizeof(head));}void addedge(int u,int v,int cap,double cost) //同时增加原边与反向边{ edge[tol].to=v; edge[tol].cap=cap; edge[tol].cost=cost; edge[tol].flow=0; edge[tol].next=head[u]; head[u]=tol++; edge[tol].to=u; edge[tol].cap=0; edge[tol].cost=-cost; edge[tol].flow=0; edge[tol].next=head[v]; head[v]=tol++;}/* * SPFA 算法判断是否存在s到t的通路 */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) //遍历所有与u临接的点 { 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); } } } } return (pre[t]!=-1); //返回是否s到t是否有路径}/* * int s 起点 * int t 终点 */int minCostMaxFlow(int s,int t,double &cost){ int flow=0; while(spfa(s,t)) { int minn=INF; //当前路径可增广值 for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to]) //因为建图时每增加一条边会同时加入它的反向边,因此i^1为找出与i刚好相反的部分 { if(minn>edge[i].cap-edge[i].flow) minn=edge[i].cap-edge[i].flow; } for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to]) //修改图,计算花费 { edge[i].flow+=minn; edge[i^1].flow-=minn; cost+=edge[i].cost*minn; } flow+=minn; } return flow;}int main(){ int T; scanf("%d",&T); while(T--) { int n=0,m=0; scanf("%d%d",&n,&m); init(n+2); for(int i=1; i<=n; i++) { scanf("%d%d",person+i,thing+i); person[i]-=thing[i]; } for(int i=0; i<m; i++) { int u=0,v=0,cap=0; double p; scanf("%d%d%d%lf",&u,&v,&cap,&p); p = -log2(1.0-p); if(cap>1) addedge(u,v,cap-1,p); if(cap>0) addedge(u,v,1,0); } for(int i=1; i<=n; i++) { if(person[i]>0) addedge(0,i,person[i],0); else addedge(i,n+1,-person[i],0); } double cost = 0; minCostMaxFlow(0,n+1,cost); printf("%.2f\n",1.0-pow(2,-cost)); } return 0;}
- hdu 5988 Coding Contest (最小费用流)
- HDU 5988 Coding Contest (最小费用流)
- HDU 5988 Coding Contest(费用流)
- HDU-5988-Coding Contest(费用流)
- HDU 5988 Coding Contest(费用流)
- HDU 5988 Coding Contest(最小费用最大流)
- hdu 5988 Coding Contest(最小费用流 骚)
- hdu 5988 Coding Contest (费用流)
- 【HDU 5988】 Coding Contest 【费用流】
- HDU-5988 Coding Contest 最大费用流
- hdu 5988 Coding Contest 费用流
- HDU 5988 Coding Contest 最小费用流变形
- [最大费用最大流]HDU 5988 Coding Contest
- hdu 5988 Coding Contest (费用流变形)
- hdu 5988 Coding Contest 青岛G题 费用流以及一些感想吧
- HDU 5988 Coding Contest 2016青岛G题浮点费用流
- HDU-5988 Coding Contest
- 2016年青岛区域赛 Coding Contest(费用流)
- Java基础时更(~11.14)
- SharedPreferencesUtil
- Android源码解析之Binder中Server和Client获得Service Manager接口
- 201710141100->利用www完成post请求
- Ionic3学习笔记(七)Storage
- HDU 5988 Coding Contest (最小费用流)
- 将Shiro整到SSM中(基于maven)
- 原码,补码,反码
- "[用户名] is not in the sudoers file"(已解决)
- 摆渡人 ——克莱尔.麦克福尔 读后感
- <二分答案+spfa验证>codevs 1183 泥泞的道路
- Spring boot 与 MySQL 的使用
- Android的TextView的字体倾斜
- MySQL(一):基本原理