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 ... 
随机推荐
- javaweb:Response/Request的概述 (转发、重定向、get/post)转
			请求响应流程图 1]response 1 response概述 response是Servlet.service方法的一个参数,类型为javax.servlet.http.HttpServletR ... 
- 开发跨平台应用解决方案-uniapp  真心不错,支持一波
			uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架,开发者编写一套代码,可编译到iOS.Android.微信小程序等多个平台. 用了mui,H5+一年多了,感觉dcloud 最近推出的 ... 
- [转载]C / C++ 计算程序运行的时间
			原文链接:https://blog.csdn.net/qq_36667170/article/details/79507547 在学数据结构过程中老师让查看不同算法的运行时间,然后让自己打印运行时间. ... 
- 在mybatis中,在列表分页查询过程中造成集合属性数据丢失的问题
			由于在进行多表关联分页查询时,某一个集合属性的多条数据正好位于2页的分割处,那么就会造成在前一页获取到的该集合属性的集合内部数据不全,因为其余数据被分到了第二页, 因此建议在进行集合属性的封装时,最好 ... 
- ajax异步 —— javascript
			目录 ajax是什么 原生ajax jquery ajax ajax跨域 ajax是什么 作用:不必重新加载整个页面,更新部分页面内容. 大概使用过程:通过后台提供的数据接口,ajax获取数据,动态修 ... 
- 工具使用——使用XShell连接linux系统
			1.首先到官网取下载一个XShell安装包,根据提示安装成功. 2.打开软件,点击新建连接 3.在新建连接页面输入,主机名称.主机地址.端口号,点击确定按钮. 4.在弹出的会话窗口中,选中我们刚刚创建 ... 
- sql 占位符及部分时间函数
			Mysql 预处理占位符 %s -- 表示字段串 %d -- 表示整形数字 %f -- 表示浮点数 (UNIX_TIMESTAMP(DATE_SUB(now(), INTERVAL jp_days D ... 
- python socket使用
			自学python,先在菜鸟教程网自学,然后买了本书看.又从同事那里淘到了某个培训学校python教学视频,查缺补漏.视频是用python3.0讲的,讲解的很不错,中间有让写作业,这个我很喜欢.这几天看 ... 
- Codeforces 898 贪心关闭最少闹钟 优先队列最少操作构造N/2squares  讨论情况哈希数字串分割a+b=c
			A /* Huyyt */ #include <bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define mkp(a,b) ... 
- pikachu-xss和csrf
			简介 XSS是一种发生在Web前端的漏洞,所以其危害的对象也主要是前端用户 XSS漏洞可以用来进行钓鱼攻击.前端js挖矿.盗取用户cookie,甚至对主机进行远程控制 攻击流程 假设存在漏洞的是一个论 ... 
