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 ...
随机推荐
- 05、解剖CEL文件各版本格式和读取方法(非R语言)
相比DAT文件,网络上更支持CEL级别的文件.CEL已经把DAT图像转换成数据了,而且CEL比DAT所占空间小得多.介绍一下CEL文件的格式,CEL文件有文本文件(TextCelFile,版本3).B ...
- CentOS6.6安装使用MyCat
https://blog.csdn.net/u012948302/article/details/78902092 1. 安装Java环境MyCAT 是使用 JAVA 语言进行编写开发,使用前需要先安 ...
- 使用vue-cli构建vue项目流程
下载: nodejs 安装 npm vue-cli -g 生成项目 vue init webpack elementui2 (elementui2是我的项目名称) 进入项目 cd elementui2 ...
- grunt接触
grunt使用 以下内容均为已经安装好grunt,具体grunt的安装过程不述,可以参考grunt的相关资料. 1.项目初始化grunt 在项目文件夹的根目录下面,打开命令行grunt init,执行 ...
- 【微信小程序】图片压缩-纯质量压缩,非长宽裁剪压缩
原理:利用canvas来实现,将图片绘制到canvas上,然后canvas转图片时,微信提供的一个方法wx.canvasToTempFilePath(Object object, Object t ...
- Linux学习--第八天--acl、SetUID、SetGID、chattr、lsattr、sudo
acl权限 文件只能有一个所属组 acl就是不管用户什么组了,直接针对某个文件给他特定权限. acl需要所在分区文件系统的支持. df -h #查看分区 dumpe2fs -h /dev/sda3 # ...
- Linux中配置jdk环境变量出错:bad ELF interpreter: No such file or directory解决方法
yum install glibc.i686 重新安装,javac成功 如果还有如下类系错误 再继续安装包 error while loading shared libraries: libstdc+ ...
- [POJ1664]放苹果(动态规划)
[POJ1664]放苹果 Description 把M个同样的苹果放在N个同样的盘子里,允许有的盘子空着不放,问共有多少种不同的分法?(用K表示)5,1,1和1,5,1 是同一种分法. Input 第 ...
- GlobalLock锁定一个全局内存对象
GlobalLock BAIPro
- Spring mvc数据转换 格式化 校验(转载)
原文地址:http://www.cnblogs.com/linyueshan/p/5908490.html 数据绑定流程 1. Spring MVC 主框架将 ServletRequest 对象及目标 ...