题目链接: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
",(1.0-pow(di,-cost)));
121 }
122 return 0;
123 }