题意:一个网络流的图,有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就好了。

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=;
  4. const int INF =0x3f3f3f3f;
  5. const double esp=1e-;
  6. struct Edge
  7. {
  8. int from,to,cap,flow; double cost;
  9. Edge(int u,int v,int ca,int f,double co):from(u),to(v),cap(ca),flow(f),cost(co){};
  10. };
  11.  
  12. struct MCMF
  13. {
  14. int n,m,s,t;
  15. vector<Edge> edges;
  16. vector<int> G[maxn];
  17. int inq[maxn];//是否在队列中
  18. double d[maxn];//距离
  19. int p[maxn];//上一条弧
  20. int a[maxn];//可改进量
  21.  
  22. void init(int n)//初始化
  23. {
  24. this->n=n;
  25. for(int i=;i<=n;i++)
  26. G[i].clear();
  27. edges.clear();
  28. }
  29.  
  30. void AddEdge(int from,int to,int cap,double cost)//加边
  31. {
  32. edges.push_back(Edge(from,to,cap,,cost));
  33. edges.push_back(Edge(to,from,,,-cost));
  34. int m=edges.size();
  35. G[from].push_back(m-);
  36. G[to].push_back(m-);
  37. }
  38.  
  39. bool SPFA(int s,int t,int &flow,double &cost)//寻找最小费用的增广路,使用引用同时修改原flow,cost
  40. {
  41. for(int i=;i<n;i++)
  42. d[i]=INF;
  43. memset(inq,,sizeof(inq));
  44. d[s]=;inq[s]=;p[s]=;a[s]=INF;
  45. queue<int> Q;
  46. Q.push(s);
  47. while(!Q.empty())
  48. {
  49. int u=Q.front();
  50. Q.pop();
  51. inq[u]--;
  52. for(int i=;i<G[u].size();i++)
  53. {
  54. Edge& e=edges[G[u][i]];
  55. if(e.cap>e.flow && d[e.to]-d[u]-e.cost>esp)//满足可增广且可变短
  56. {
  57. d[e.to]=d[u]+e.cost;
  58. p[e.to]=G[u][i];
  59. a[e.to]=min(a[u],e.cap-e.flow);
  60. if(!inq[e.to])
  61. {
  62. inq[e.to]++;
  63. Q.push(e.to);
  64. }
  65. }
  66. }
  67. }
  68. if(d[t]==INF) return false;//汇点不可达则退出
  69. flow+=a[t];
  70. cost+=d[t]*a[t];
  71. int u=t;
  72. while(u!=s)//更新正向边和反向边
  73. {
  74. edges[p[u]].flow+=a[t];
  75. edges[p[u]^].flow-=a[t];
  76. u=edges[p[u]].from;
  77. }
  78. return true;
  79. }
  80.  
  81. double MincotMaxflow(int s,int t)
  82. {
  83. int flow=;
  84. double cost=;
  85. while(SPFA(s,t,flow,cost));
  86. return cost;
  87. }
  88. }MM;
  89. int main(){
  90. int _;scanf("%d",&_);
  91. while(_--){
  92. int n,m;
  93. scanf("%d%d",&n,&m);
  94. MM.init(n+);
  95. for(int i=;i<=n;i++){
  96. int s,b; scanf("%d%d",&s,&b);
  97. int T=s-b;
  98. if(T>) MM.AddEdge(,i,s-b,);
  99. else if(T<) MM.AddEdge(i,n+,b-s,);
  100. }
  101. for(int i=;i<=m;i++){
  102. int u,v,c;double p;
  103. scanf("%d%d%d%lf",&u,&v,&c,&p);
  104. p=-log2(1.0-p);///求最大不被破坏->最小被破坏
  105. if(c>)
  106. MM.AddEdge(u,v,,);
  107. if(c->)
  108. MM.AddEdge(u,v,c-,p);
  109. }
  110. double ans=MM.MincotMaxflow(,n+);
  111. ans=-pow(,-ans);
  112. printf("%.2f\n",ans);
  113.  
  114. }
  115. }

hdu5988(费用流,对数相乘做加法)的更多相关文章

  1. 2016青岛区域赛.Coding Contest(费用流 + 概率计算转换为加法计算)

    Coding Contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)To ...

  2. 洛谷P2045 方格取数加强版(费用流)

    题意 题目链接 Sol 这题能想到费用流就不难做了 从S向(1, 1)连费用为0,流量为K的边 从(n, n)向T连费用为0,流量为K的边 对于每个点我们可以拆点限流,同时为了保证每个点只被经过一次, ...

  3. 【BZOJ2879】【NOI2012】美食节(费用流)

    [BZOJ2879][NOI2012]美食节(费用流) 题面 BZOJ 洛谷 题解 一眼就会思路了吧. 把每个厨师拆点,拆分为他最多能要做的菜的个数,即\(\sum p_i\) 然后把每个菜向厨师的每 ...

  4. 【费用流】NOI2008志愿者招募

    1061: [Noi2008]志愿者招募 Time Limit: 20 Sec  Memory Limit: 162 MBSubmit: 5171  Solved: 3089[Submit][Stat ...

  5. POJ 2516 基础费用流

    题意       有n个顾客,m个供应商,k种货物,给你顾客对于每种货物的要求个数,和供应商对于每种货物的现有量,以及供应每种货物的时候供应商和顾客之间的运输单价,问你满足所有顾客的前提下的最小运输费 ...

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

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

  7. 【费用流】hdu5988 Coding Contest

    从源点向每个点连接容量为该点人数,费用为1的边, 把原图中的每条边拆成两条,一条容量为1,费用为1,另一条容量为ci-1,费用为1-pi 从每个点向汇点连接容量为该点面包数量,费用为1的边. 跑的费用 ...

  8. CF 277E Binary Tree on Plane (拆点 + 费用流) (KM也可做)

    题目大意: 平面上有n个点,两两不同.现在给出二叉树的定义,要求树边一定是从上指向下,即从y坐标大的点指向小的点,并且每个结点至多有两个儿子.现在让你求给出的这些点是否能构成一棵二叉树,如果能,使二叉 ...

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

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

随机推荐

  1. Windows7下Pycharm安装Keras

    1.安装Anaconda3 2.安装Pycharm 3.安装TensorFlow 一.File -> Settings -> Install 二.搜索TensorFlow -> In ...

  2. 140. 后缀数组(hash + 二分 / 后缀数组)

    题目链接 : https://www.acwing.com/problem/content/description/142/ Hash + 二分 #include <bits/stdc++.h& ...

  3. 对Elastic集群内部配置TLS加密通信及身份验证

    1.介绍 官方宣布从6.8和7.1开始,免费提供多项安全功能.其中包括tls加密通信,基于角色访问控制等功能. 可以使用企业CA证书来完成这一步骤,但是一般情况下,我们可以通过elasticsearc ...

  4. 34、Scrapy 知识总结

      Scrapy 知识总结   1.安装   pip install wheel pip install https://download.lfd.uci.edu/pythonlibs/q5gtlas ...

  5. css 超出部分显示省略号 汇总

    单行: 加宽度 overflow: hidden; text-overflow:ellipsis; white-space: nowrap; 多行: display: -webkit-box; -we ...

  6. RS chap2:利用用户行为数据

    一.用户行为数据简介 1.用户行为在个性化推荐系统中分为两种: (1)显式反馈行为:包括用户明确表示对物品喜好的行为. (2)隐式反馈行为:不能明确反应用户喜好的行为. (3)显式反馈行为和隐式反馈行 ...

  7. 常用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 ...

  8. 使用CXF开发WebService程序的总结(五):基于Map数据类型处理的的客户端和服务端代码的编写

    1. 首先我们按照List或数组等处理方式来处理Map,看看效果 1.1 在服务端的接口中添加以下方法 /** * 查询所有班级信息加上对应的学生列表 * * @return */ public Ma ...

  9. css3 加载动画

    代码 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8& ...

  10. aria2的安装与配置

    aria2安装 安装 epel 源: yum install epel-release 然后直接安装: yum install aria2 -y 配置 Aria2 创建目录与配置文件 这一步需要切换到 ...