http://acm.split.hdu.edu.cn/showproblem.php?pid=5988
题意:
在acm比赛的时候有多个桌子,桌子与桌子之间都有线路相连,每个桌子上会有一些人和一些食物,现在要吃午饭了,有些人就可能需要到别的桌子去拿食物,但是必须沿着线路走,每根线路第一个人走时没事,接下来的人走时会有一定概率使网络瘫痪,并且每根线路最多可以走c人。现在问使网络瘫痪的最低概率是多少?
思路:
建立费用流,由于概率是要相乘,这里可以转换成log后进行计算,最后再转换回来即可。
由于这题是浮点数,所以在松弛的时候需要加eps,否则会TLE。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn = 200+5; 16 const double eps = 1e-8; 17 18 int n,m; 19 20 struct Edge 21 { 22 int from, to, cap, flow; 23 double cost; 24 Edge(int u, int v, int c, int f, double w) :from(u), to(v), cap(c), flow(f), cost(w) {} 25 }; 26 27 struct MCMF 28 { 29 int n, m; 30 vector<Edge> edges; 31 vector<int> G[maxn]; 32 int inq[maxn]; 33 double d[maxn]; 34 int p[maxn]; 35 int a[maxn]; 36 37 void init(int n) 38 { 39 this->n = n; 40 for (int i = 0; i<n; i++) G[i].clear(); 41 edges.clear(); 42 } 43 44 void AddEdge(int from, int to, int cap, double cost) 45 { 46 edges.push_back(Edge(from, to, cap, 0, cost)); 47 edges.push_back(Edge(to, from, 0, 0, -cost)); 48 m = edges.size(); 49 G[from].push_back(m - 2); 50 G[to].push_back(m - 1); 51 } 52 53 bool BellmanFord(int s, int t, int &flow, double & cost) 54 { 55 for (int i = 0; i<n; i++) d[i] = INF; 56 memset(inq, 0, sizeof(inq)); 57 d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF; 58 59 queue<int> Q; 60 Q.push(s); 61 while (!Q.empty()){ 62 int u = Q.front(); Q.pop(); 63 inq[u] = 0; 64 for (int i = 0; i<G[u].size(); i++){ 65 Edge& e = edges[G[u][i]]; 66 if (e.cap>e.flow && d[e.to]>d[u] + e.cost +eps){ 67 d[e.to] = d[u] + e.cost; 68 p[e.to] = G[u][i]; 69 a[e.to] = min(a[u], e.cap - e.flow); 70 if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; } 71 } 72 } 73 } 74 75 if (d[t] == INF) return false; 76 flow += a[t]; 77 cost += d[t] * a[t]; 78 for (int u = t; u != s; u = edges[p[u]].from) 79 { 80 edges[p[u]].flow += a[t]; 81 edges[p[u] ^ 1].flow -= a[t]; 82 } 83 return true; 84 } 85 86 double MincostMaxdflow(int s, int t){ 87 int flow = 0; 88 double cost = 0; 89 while (BellmanFord(s, t, flow, cost)); 90 return cost; 91 } 92 }t; 93 94 int a[maxn],b[maxn],c[maxn]; 95 96 int main() 97 { 98 //freopen("in.txt","r",stdin); 99 int T; 100 scanf("%d",&T); 101 while(T--) 102 { 103 scanf("%d%d",&n,&m); 104 int src=0,dst=2*n+1; 105 t.init(dst+1); 106 for(int i=0;i<n;i++) 107 { 108 scanf("%d%d",&a[i],&b[i]); 109 c[i]=a[i]-b[i]; 110 if(c[i]<0) t.AddEdge(i+1,dst,-c[i],0); 111 else if(c[i]>0) t.AddEdge(src,i+1,c[i],0); 112 } 113 for(int i=0;i<m;i++) 114 { 115 int u,v,c; double p; 116 scanf("%d%d%d%lf",&u,&v,&c,&p); 117 p=-log(1-p); 118 if(c==0) continue; 119 if(c==1) t.AddEdge(u,v,1,0); 120 else if(c>1) 121 { 122 t.AddEdge(u,v,1,0); 123 t.AddEdge(u,v,c-1,p); 124 } 125 } 126 double ans = t.MincostMaxdflow(src,dst); 127 ans=exp(-ans); 128 printf("%.2f ",1-ans); 129 } 130 return 0; 131 }