hdu5988最小费用最大流浮点
Posted json-five
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu5988最小费用最大流浮点相关的知识,希望对你有一定的参考价值。
惊了,TLE半天发现浮点运算是要加esp,真是学到了。
题目链接https://www.nowcoder.com/acm/contest/207/G
题意就是给你N个点,每个点有si个人和bi个食物背包,然后是M条边,每条边有个触电概率pi,第一个人经过这条边不会触电,问你让所有人吃完饭的最小触电概率.
方法:如果si>bi 连接0到i 容量为si-bi,费用为0,否则就连接 i到n+1,容量为bi-si,费用为0
然后把每线路拆成两条,一条容量为1,费用为0,一条容量为c-1,费用为-log(1-pi)
因为最后要输出所有概率的乘积的最小值,取对数后变成负数,加上负号后最小变最大,所以再把概率取反变成(1-pi)
跑一边最短路输出1-exp(-ans)即可
#include<bits/stdc++.h> #define esp 1e-7 using namespace std; const int maxn=205; const int INF=0x3fffffff; struct Edge { int from,to,cap,flow; double cost; }; 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=0; i<=n; i++)G[i].clear(); edges.clear(); } void AddEdge(int from,int to,int cap,double cost) { Edge e; e.from=from,e.to=to,e.cap=cap,e.flow=0,e.cost=cost; edges.push_back(e); e.from=to,e.to=from,e.cap=0,e.flow=0,e.cost=-cost; edges.push_back(e); m=edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BellmanFord(int s,int t,int& flow,double& cost) { for(int i=0; i<=n; i++)d[i]=INF; memset(inq,0,sizeof(inq)); d[s]=0; inq[s]=1; p[s]=0; a[s]=INF; queue<int>Q; Q.push(s); while(!Q.empty()) { int u=Q.front(); Q.pop(); inq[u]=0; for(int i=0; i<(int)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]) { Q.push(e.to); inq[e.to]=1; } } } } 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]^1].flow-=a[t]; u=edges[p[u]].from; } return true; } double Mincost(int s,int t) { int flow=0; double cost=0; while(BellmanFord(s,t,flow,cost)); return cost; } } mcmf; int main() { int t,n,m,s,b,u,v,c; double pi; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); mcmf.init(n+2); for (int i=1; i<=n ; i++ ) { scanf("%d%d",&s,&b); if(s>b) { mcmf.AddEdge(0,i,s-b,0); } else if(b>s) { mcmf.AddEdge(i,n+1,b-s,0); } } for (int i=1; i<=m ; i++ ) { scanf("%d%d%d%lf",&u,&v,&c,&pi); if(c>0)mcmf.AddEdge(u,v,1,0); if(c-1>0) { mcmf.AddEdge(u,v,c-1,-log(1.0-pi)); } } printf("%.2lf ",1.0-exp(-mcmf.Mincost(0,n+1))); } return 0; }
以上是关于hdu5988最小费用最大流浮点的主要内容,如果未能解决你的问题,请参考以下文章
Coding Contest HDU - 5988(费用流)
HDU5988 - 2016icpc青岛 - G - Coding Contest 费用流(利用对数化乘为加