HDU 5988最小网络流(浮点数)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5988

哇,以前的模版一直T,加了优先队列优化才擦边过。

建图很好建,概率乘法化成概率加法不会化。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <vector>
  5 #include <queue>
  6 #include <algorithm>
  7 #include <cmath>
  8 using namespace std;
  9 const int maxn = 500;
 10 const int INF = 1e9;
 11 double dist[maxn];
 12 int tot,head[maxn];
 13 int pv[maxn],pe[maxn];
 14 typedef pair<double,int> P;
 15 double eps = 1e-6;
 16 struct edge
 17 {
 18     int to,pre,cap;
 19     double cost;
 20 }e[50000];
 21 void init()
 22 {
 23     tot = 0;
 24     memset(head,-1,sizeof(head));
 25 }
 26 void add(int from,int to,int cap,double cost)
 27 {
 28     e[tot].pre = head[from];
 29     e[tot].to = to;
 30     e[tot].cap = cap;
 31     e[tot].cost = cost;
 32     head[from] = tot++;
 33 }
 34 void addedge(int from,int to,int cap,double cost)
 35 {
 36     add(from,to,cap,cost);
 37     add(to,from,0,-cost);
 38 }
 39 int n;
 40 double min_cost_flow(int s,int t,int f,int& max_flow)
 41 {
 42     double ret = 0.0;
 43     while(f>0)
 44     {
 45         priority_queue<P,vector<P>,greater<P> >q;
 46         for(int i=0;i<maxn;i++) dist[i] = INF;
 47         dist[s] = 0.0;
 48         q.push(P(0,s));
 49         while(!q.empty())
 50         {
 51             P cur = q.top(); q.pop();
 52             int v = cur.second;
 53             if(dist[v]<cur.first) continue;
 54             for(int i=head[v];i>=0;i=e[i].pre)
 55             {
 56                 int to = e[i].to,cap = e[i].cap;
 57                 double cost = e[i].cost;
 58                 if(cap>0&&(dist[to]-(dist[v]+cost))>=eps)
 59                 {
 60                     pv[to] = v,pe[to] = i;
 61                     dist[to] = dist[v] + cost;
 62                     q.push(P(dist[to],to));
 63                 }
 64             }
 65         }
 66         if(fabs(dist[t]-INF)<=eps) return ret;///同一目的地,每次增广路都是最小费用
 67         ///当所有边的流量都流净后,即没有残余网络,返回。
 68         int d = f;
 69         for(int v=t;v!=s;v=pv[v])
 70         {
 71             d = min(d,e[pe[v]].cap);
 72         }
 73         f -= d;
 74         max_flow += d;
 75         ret += (double)d*dist[t]; ///走一单位就消耗dist[t]
 76         for(int v=t;v!=s;v=pv[v])
 77         {
 78             e[pe[v]].cap -= d;
 79             e[pe[v]^1].cap += d;
 80         }
 81     }
 82     return ret;
 83 }
 84 int main()
 85 {
 86     int T;scanf("%d",&T);
 87     while(T--)
 88     {
 89         int m;
 90         init();
 91         scanf("%d %d",&n,&m);
 92         int s = n+1;
 93         int t = n+2;
 94         for(int i=1;i<=n;i++)
 95         {
 96             int si,bi;
 97             scanf("%d %d",&si,&bi);
 98             int x = si-bi;
 99             if(x>0) addedge(s,i,x,0);
100             else if(x<0) addedge(i,t,-x,0);
101         }
102         int u,v,c;
103         double p;
104         for(int i=1;i<=m;i++)
105         {
106             scanf("%d %d %d %lf",&u,&v,&c,&p);
107             p = -1.0*log2(1.0-p);
108             if(c>0)
109             {
110                 addedge(u,v,1,0);///第一个人不用费用
111             }
112             if(c-1>0)
113             {
114                 addedge(u,v,c-1,p);
115             }
116         }
117         int max_flow = 0;
118         double cost =  min_cost_flow(s,t,INF,max_flow);
119         double di = 2.0;
120         printf("%.2f\n",(1.0-pow(di,-cost)));
121     }
122     return 0;
123 }

 

posted @ 2017-10-01 17:13  卷珠帘  阅读(463)  评论(0编辑  收藏  举报