这题有一个非常坑人的地方, product 这个单词在这题里是 “相乘" 的意思.
然后就是最小割模型的建立,s=0,t=m+n+1 然后从s到1-m建权为Ci一条边,从 m+1 - m+n 建立到t的权值为Ri的边。 然后每个伞兵的坐标(x,y) 建立x->y权为无穷大的边.
这题关键的一点叫我们求所有费用的乘积最小,可以知道的是用最小割模型求出的是所有费用的和, 如果想处理乘法运算看似很难办, 但是有一种很灵巧的方法:
将每条边的权值先取对数(log是以e为底,log10是以10为底),然后其中网络流中的操作都为+-,对于对数就相当于乘除, 可知如果最后求出去对数后的权值和最大,然后exp(e的平方)一下就可以得到最大的总乘积.
以后遇到乘法难以处理时,想想用对数转化为+- 的运算是否可以解决.
Paratroopers
Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the Mars. Recently, the commanders of the Earth are informed by their spies that the invaders of Mars want to land some paratroopers in the m × n grid yard of one their main weapon factories in order to destroy it. In addition, the spies informed them the row and column of the places in the yard in which each paratrooper will land. Since the paratroopers are very strong and well-organized, even one of them, if survived, can complete the mission and destroy the whole factory. As a result, the defense force of the Earth must kill all of them simultaneously after their landing. In order to accomplish this task, the defense force wants to utilize some of their most hi-tech laser guns. They can install a gun on a row (resp. column) and by firing this gun all paratroopers landed in this row (resp. column) will die. The cost of installing a gun in the ith row (resp. column) of the grid yard is ri (resp. ci ) and the total cost of constructing a system firing all guns simultaneously is equal to the product of their costs. Now, your team as a high rank defense group must select the guns that can kill all paratroopers and yield minimum total cost of constructing the firing system. Input Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing three integers 1 ≤ m ≤ 50 , 1 ≤ n ≤ 50 and 1 ≤ l ≤ 500 showing the number of rows and columns of the yard and the number of paratroopers respectively. After that, a line with m positive real numbers greater or equal to 1.0 comes where the ith number is ri and then, a line with n positive real numbers greater or equal to 1.0 comes where the ith number is ci. Finally, l lines come each containing the row and column of a paratrooper. Output For each test case, your program must output the minimum total cost of constructing the firing system rounded to four digits after the fraction point. Sample Input 1 4 4 5 2.0 7.0 5.0 2.0 1.5 2.0 2.0 8.0 1 1 2 2 3 3 4 4 1 4 Sample Output 16.0000 Source |
1 #include <stdio.h> 2 #include <string.h> 3 #include <math.h> 4 #include <string> 5 #include <iostream> 6 using namespace std; 7 #define N 110 8 #define M 5*N*N 9 #define INF 0x3ffffff 10 11 struct node 12 { 13 int to,next; 14 double w; 15 }edge[M]; 16 17 int cnt,pre[N]; 18 int s,t; 19 int nn; 20 int n,m; 21 int lv[N],gap[N]; 22 23 void add_edge(int u,int v,double w) 24 { 25 edge[cnt].to=v; 26 edge[cnt].w=w; 27 edge[cnt].next=pre[u]; 28 pre[u]=cnt++; 29 } 30 31 double sdfs(int k,double w) 32 { 33 if(k==t) return w; 34 double f=0; 35 int mi=nn-1; 36 for(int p=pre[k];p!=-1;p=edge[p].next) 37 { 38 int v=edge[p].to; 39 if(edge[p].w!=0) 40 { 41 if(lv[k]==lv[v]+1) 42 { 43 double tmp=sdfs(v,min(w-f,edge[p].w)); 44 f+=tmp; 45 edge[p].w-=tmp; 46 edge[p^1].w+=tmp; 47 if(f==w||lv[s]==nn) return f; 48 } 49 if(lv[v]<mi) mi=lv[v]; 50 } 51 } 52 if(f==0) 53 { 54 gap[lv[k]]--; 55 if(gap[lv[k]]==0) 56 { 57 lv[s]=nn; 58 return f; 59 } 60 lv[k]=mi+1; 61 gap[lv[k]]++; 62 } 63 return f; 64 } 65 66 double sap() 67 { 68 nn=t+1; 69 double sum=0; 70 memset(lv,0,sizeof(lv)); 71 memset(gap,0,sizeof(gap)); 72 gap[0]=nn; 73 while(lv[s]<nn) 74 { 75 sum+=sdfs(s,INF); 76 } 77 return sum; 78 } 79 int main() 80 { 81 int t1,p; 82 scanf("%d",&t1); 83 while(t1--) 84 { 85 cnt=0; 86 memset(pre,-1,sizeof(pre)); 87 scanf("%d%d%d",&n,&m,&p); 88 s=0; 89 t=n+m+1; 90 for(int i=1;i<=n;i++) 91 { 92 double w; 93 scanf("%lf",&w); 94 add_edge(s,i,log(w)); 95 add_edge(i,s,0); 96 } 97 for(int i=1;i<=m;i++) 98 { 99 double w; 100 scanf("%lf",&w); 101 add_edge(n+i,t,log(w)); 102 add_edge(t,n+i,0); 103 } 104 for(int i=0;i<p;i++) 105 { 106 int x,y; 107 scanf("%d%d",&x,&y); 108 add_edge(x,n+y,INF); 109 add_edge(n+y,x,0); 110 } 111 printf("%.4lf\n",exp(sap())); 112 } 113 return 0; 114 }