1. 程式人生 > >hdu5988最小費用最大流浮點

hdu5988最小費用最大流浮點

can oid fin 所有 clas color exp ems 最小值

驚了,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\n",1.0-exp(-mcmf.Mincost(0,n+1))); } return 0; }

hdu5988最小費用最大流浮點