hdu5988(费用流,对数相乘做加法)
题意:一个网络流的图,有n个点,从1~n,然后m条边,每个点有两个值,一个是人的数量si一个是饭的数量bi。每条m边有容量ci,还有走上去可能踩断电线的概率pi(第一次踩上去没有事,之后都要p概率)。问让所有人吃到饭的前提下断电线的最小概率是多少。
解法:每条边有走的次数(流量),每条边走一次发生破坏概率为p(流量1,费用p),容易想到费用流。可是费用流往往是费用相加的,这个是概率,只能相乘。有什么办法,log函数可以把乘除法转换为加减法。所以对每个概率取个log当成费用就行了。
注意,这个概率是踩坏的概率,你数学思维一下,求总的踩坏概率不可能会是说全部都是踩坏的概率相乘吧,我也可以有一些边是可以吧被拆坏,所以我们需要求对立面
这时候就应该从反方向进行考虑,求踩坏的最小概率,就是求不踩坏的最大概率,1-p后取log,和以上同理,求出了最大费用。取出来还回去后用1减一下就好了。
新建源点s,汇点t,对于S>B的需要人走,从源点连一条流量为S[i]-B[i],费用为0(出门不需要费用)的边过去,add(s,i,S[i]-B[i],0),对于s<b的,add(i,t,B[i]-S[i],0)。
为什么要这样建边呢,是因为从源点s出来的人要到汇点t去,到汇点的边就相当于到这个点的一些人吃了面包走到了汇点。
然后还有一个问题,就是第一次踩的时候,不会触发,那么从原有的边中取一条出来,流量1,费用0就好了。
- #include<bits/stdc++.h>
- using namespace std;
- const int maxn=;
- const int INF =0x3f3f3f3f;
- const double esp=1e-;
- struct Edge
- {
- int from,to,cap,flow; double cost;
- Edge(int u,int v,int ca,int f,double co):from(u),to(v),cap(ca),flow(f),cost(co){};
- };
- struct MCMF
- {
- int n,m,s,t;
- vector<Edge> edges;
- vector<int> G[maxn];
- int inq[maxn];//是否在队列中
- double d[maxn];//距离
- int p[maxn];//上一条弧
- int a[maxn];//可改进量
- void init(int n)//初始化
- {
- this->n=n;
- for(int i=;i<=n;i++)
- G[i].clear();
- edges.clear();
- }
- void AddEdge(int from,int to,int cap,double cost)//加边
- {
- edges.push_back(Edge(from,to,cap,,cost));
- edges.push_back(Edge(to,from,,,-cost));
- int m=edges.size();
- G[from].push_back(m-);
- G[to].push_back(m-);
- }
- bool SPFA(int s,int t,int &flow,double &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost
- {
- for(int i=;i<n;i++)
- d[i]=INF;
- memset(inq,,sizeof(inq));
- d[s]=;inq[s]=;p[s]=;a[s]=INF;
- queue<int> Q;
- Q.push(s);
- while(!Q.empty())
- {
- int u=Q.front();
- Q.pop();
- inq[u]--;
- for(int i=;i<G[u].size();i++)
- {
- Edge& e=edges[G[u][i]];
- if(e.cap>e.flow && d[e.to]-d[u]-e.cost>esp)//满足可增广且可变短
- {
- d[e.to]=d[u]+e.cost;
- p[e.to]=G[u][i];
- a[e.to]=min(a[u],e.cap-e.flow);
- if(!inq[e.to])
- {
- inq[e.to]++;
- Q.push(e.to);
- }
- }
- }
- }
- if(d[t]==INF) return false;//汇点不可达则退出
- flow+=a[t];
- cost+=d[t]*a[t];
- int u=t;
- while(u!=s)//更新正向边和反向边
- {
- edges[p[u]].flow+=a[t];
- edges[p[u]^].flow-=a[t];
- u=edges[p[u]].from;
- }
- return true;
- }
- double MincotMaxflow(int s,int t)
- {
- int flow=;
- double cost=;
- while(SPFA(s,t,flow,cost));
- return cost;
- }
- }MM;
- int main(){
- int _;scanf("%d",&_);
- while(_--){
- int n,m;
- scanf("%d%d",&n,&m);
- MM.init(n+);
- for(int i=;i<=n;i++){
- int s,b; scanf("%d%d",&s,&b);
- int T=s-b;
- if(T>) MM.AddEdge(,i,s-b,);
- else if(T<) MM.AddEdge(i,n+,b-s,);
- }
- for(int i=;i<=m;i++){
- int u,v,c;double p;
- scanf("%d%d%d%lf",&u,&v,&c,&p);
- p=-log2(1.0-p);///求最大不被破坏->最小被破坏
- if(c>)
- MM.AddEdge(u,v,,);
- if(c->)
- MM.AddEdge(u,v,c-,p);
- }
- double ans=MM.MincotMaxflow(,n+);
- ans=-pow(,-ans);
- printf("%.2f\n",ans);
- }
- }
hdu5988(费用流,对数相乘做加法)的更多相关文章
- 2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)
Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)To ...
- 洛谷P2045 方格取数加强版(费用流)
题意 题目链接 Sol 这题能想到费用流就不难做了 从S向(1, 1)连费用为0,流量为K的边 从(n, n)向T连费用为0,流量为K的边 对于每个点我们可以拆点限流,同时为了保证每个点只被经过一次, ...
- 【BZOJ2879】【NOI2012】美食节(费用流)
[BZOJ2879][NOI2012]美食节(费用流) 题面 BZOJ 洛谷 题解 一眼就会思路了吧. 把每个厨师拆点,拆分为他最多能要做的菜的个数,即\(\sum p_i\) 然后把每个菜向厨师的每 ...
- 【费用流】NOI2008志愿者招募
1061: [Noi2008]志愿者招募 Time Limit: 20 Sec Memory Limit: 162 MBSubmit: 5171 Solved: 3089[Submit][Stat ...
- POJ 2516 基础费用流
题意 有n个顾客,m个供应商,k种货物,给你顾客对于每种货物的要求个数,和供应商对于每种货物的现有量,以及供应每种货物的时候供应商和顾客之间的运输单价,问你满足所有顾客的前提下的最小运输费 ...
- HDU5988 - 2016icpc青岛 - G - Coding Contest 费用流(利用对数化乘为加
HDU5988 题意: 有n个区域,每个区域有s个人,b份饭.现在告诉你每个区域间的有向路径,每条路有容量和损坏路径的概率.问如何走可以使得路径不被破坏的概率最小.第一个人走某条道路是百分百不会损坏道 ...
- 【费用流】hdu5988 Coding Contest
从源点向每个点连接容量为该点人数,费用为1的边, 把原图中的每条边拆成两条,一条容量为1,费用为1,另一条容量为ci-1,费用为1-pi 从每个点向汇点连接容量为该点面包数量,费用为1的边. 跑的费用 ...
- CF 277E Binary Tree on Plane (拆点 + 费用流) (KM也可做)
题目大意: 平面上有n个点,两两不同.现在给出二叉树的定义,要求树边一定是从上指向下,即从y坐标大的点指向小的点,并且每个结点至多有两个儿子.现在让你求给出的这些点是否能构成一棵二叉树,如果能,使二叉 ...
- hdu-5988 Coding Contest(费用流)
题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
随机推荐
- Windows7下Pycharm安装Keras
1.安装Anaconda3 2.安装Pycharm 3.安装TensorFlow 一.File -> Settings -> Install 二.搜索TensorFlow -> In ...
- 140. 后缀数组(hash + 二分 / 后缀数组)
题目链接 : https://www.acwing.com/problem/content/description/142/ Hash + 二分 #include <bits/stdc++.h& ...
- 对Elastic集群内部配置TLS加密通信及身份验证
1.介绍 官方宣布从6.8和7.1开始,免费提供多项安全功能.其中包括tls加密通信,基于角色访问控制等功能. 可以使用企业CA证书来完成这一步骤,但是一般情况下,我们可以通过elasticsearc ...
- 34、Scrapy 知识总结
Scrapy 知识总结 1.安装 pip install wheel pip install https://download.lfd.uci.edu/pythonlibs/q5gtlas ...
- css 超出部分显示省略号 汇总
单行: 加宽度 overflow: hidden; text-overflow:ellipsis; white-space: nowrap; 多行: display: -webkit-box; -we ...
- RS chap2:利用用户行为数据
一.用户行为数据简介 1.用户行为在个性化推荐系统中分为两种: (1)显式反馈行为:包括用户明确表示对物品喜好的行为. (2)隐式反馈行为:不能明确反应用户喜好的行为. (3)显式反馈行为和隐式反馈行 ...
- 常用Java中response.setContentType参数
image/bmp BMP image/png PNG image/gif GIF image/jpeg JPEG image/tiff TIFF image/x-dcx DCX image/x-pc ...
- 使用CXF开发WebService程序的总结(五):基于Map数据类型处理的的客户端和服务端代码的编写
1. 首先我们按照List或数组等处理方式来处理Map,看看效果 1.1 在服务端的接口中添加以下方法 /** * 查询所有班级信息加上对应的学生列表 * * @return */ public Ma ...
- css3 加载动画
代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8& ...
- aria2的安装与配置
aria2安装 安装 epel 源: yum install epel-release 然后直接安装: yum install aria2 -y 配置 Aria2 创建目录与配置文件 这一步需要切换到 ...