第一个最小割,理解了好一会。
实数的最大流,注意eps,然后把乘法取log后变为加法。
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <queue> 5 using namespace std; 6 #define eps 1e-8 7 #define INF 0x3f3f3f3f 8 int dis[201],first[201]; 9 int n,m,t; 10 struct node 11 { 12 int u,v,next,re; 13 double w; 14 } edge[400001]; 15 void CL() 16 { 17 t = 1; 18 memset(first,-1,sizeof(first)); 19 } 20 void add(int u,int v,double w) 21 { 22 edge[t].u = u; 23 edge[t].v = v; 24 edge[t].w = w; 25 edge[t].re = t+1; 26 edge[t].next = first[u]; 27 first[u] = t ++; 28 edge[t].u = v; 29 edge[t].v = u; 30 edge[t].w = 0; 31 edge[t].re = t-1; 32 edge[t].next = first[v]; 33 first[v] = t ++; 34 } 35 int bfs() 36 { 37 int u,i,v; 38 memset(dis,-1,sizeof(dis)); 39 queue<int> que; 40 que.push(0); 41 dis[0] = 0; 42 while(!que.empty()) 43 { 44 u = que.front(); 45 que.pop(); 46 for(i = first[u]; i != -1; i = edge[i].next) 47 { 48 v = edge[i].v; 49 if(edge[i].w > eps&&dis[v] < 0) 50 { 51 dis[v] = dis[u]+1; 52 que.push(v); 53 } 54 } 55 } 56 if(dis[n+m+1] > 0) return 1; 57 else return 0; 58 } 59 double dfs(int u,double step) 60 { 61 int i,v; 62 double temp; 63 if(u == n+m+1) return step;//n+m+1是汇点 64 for(i = first[u]; i != -1; i = edge[i].next) 65 { 66 v = edge[i].v; 67 if(edge[i].w > eps&&dis[v] == dis[u]+1&&(temp = dfs(v,min(step,edge[i].w)))) 68 { 69 edge[i].w -= temp; 70 edge[edge[i].re].w += temp; 71 return temp; 72 } 73 } 74 return 0; 75 } 76 int main() 77 { 78 int i,l,cas,sv,ev; 79 double temp,ans,res; 80 scanf("%d",&cas); 81 while(cas--) 82 { 83 CL(); 84 scanf("%d%d%d",&n,&m,&l); 85 for(i = 1; i <= n; i ++) 86 { 87 scanf("%lf",&temp); 88 add(0,i,log(temp)); 89 } 90 for(i = 1; i <= m; i ++) 91 { 92 scanf("%lf",&temp); 93 add(n+i,n+m+1,log(temp)); 94 } 95 for(i = 1; i <= l; i ++) 96 { 97 scanf("%d%d",&sv,&ev); 98 add(sv,n+ev,INF); 99 } 100 ans = 0; 101 while(bfs()) 102 { 103 res = dfs(0,INF);//注意0是源点 104 if(res > eps) 105 ans += res; 106 else 107 break;//注意这里 108 } 109 printf("%.4f\n",exp(ans)); 110 } 111 return 0; 112 }