题目链接:http://poj.org/problem?id=3308
题目大意:
在一个m*n的格子里(m,n<=50)的某些格子会落下一个敌人。
在某一行(列)放置一个炮可以把这一行(列)的所有敌人杀死,而在某一行(列)放置一个炮要花费ri(ci),总的花费等于所有放置的炮的花费的乘积,求最小花费。
题目思路:
对于一个敌人(x,y)可知,要么选择在rx放置,要么选择在cy放置。
如果我们构造这样一张图
s --> x --> y --> t,
s --> x的权值是rx。
y --> t的权值是cy。
x --> y的权值极大。
那么我们可以知道如果要打到(x,y)相当于是走过 x --> y这条边。
而用网络流的角度,那么走过x --> y这条边的流是受s --> x 和 y --> t 控制的。
到此我们把这个问题转化为了一个二分图的问题,构造出一个这样的图,走一遍最大流(最小割)即可。
代码:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <math.h>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#define ll __int64
#define ls rt<<1
#define rs ls|1
#define lson l,mid,ls
#define rson mid+1,r,rs
#define middle (l+r)>>1
#define eps (1e-8)
#define type int
#define clr_all(x,c) memset(x,c,sizeof(x))
#define clr(x,c,n) memset(x,c,sizeof(x[0])*(n+1))
#define MOD (1000000007)
#define inf (0x3f3f3f3f)
#define pi (acos(-1.0))
#define _max(x,y) (((x)>(y))? (x):(y))
#define _min(x,y) (((x)<(y))? (x):(y))
#define _abs(x) ((x)<0? (-(x)):(x))
#define getmin(x,y) (x= (x<0 || (y)<x)? (y):x)
#define getmax(x,y) (x= ((y)>x)? (y):x)
template <class T> void _swap(T &x,T &y){T t=x;x=y;y=t;}
int TS,cas=1;
const int M=100+5;
int m,n,l;
struct sap{
int n;
double flow[M][M];
int cur[M],pre[M],dis[M],gap[M];
void init(int _n){
n=_n;
for(int i=0;i<n;i++)
for(int j=0;j<n;j++)
flow[i][j]=0.0;
}
void insert(int u,int v,double f){flow[u][v]=f;}
double maxFlow(int s,int t){
clr(dis,0,n),clr(gap,0,n),clr(cur,0,n);
gap[0]=n,pre[s]=s;
double a,res=0;
for(int u=s;dis[s]<n;){
if(u==t){
for(a=-1.0;u!=s;u=pre[u])
getmin(a,flow[pre[u]][u]);
for(u=t;u!=s;u=pre[u])
flow[pre[u]][u]-=a,flow[u][pre[u]]+=a;
res+=a;
}
bool ok=0;
for(int v=cur[u];v<n;v++){
if(dis[u]==dis[v]+1 && flow[u][v]>=eps){
pre[v]=u,cur[u]=v,u=v;
ok=1;break;
}
}
if(!ok){
int mindis=n-1;
for(int v=0;v<n;v++)
if(flow[u][v]>=eps && mindis>dis[v])
mindis=dis[v],cur[u]=v;
if(--gap[dis[u]]==0) break;
gap[dis[u]=mindis+1]++,u=pre[u];
}
}
return res;
}
}p;
void run(){
int i,j;
scanf("%d%d%d",&m,&n,&l);
p.init(m+n+2);
double r,c;
int x,y;
for(i=1;i<=m;i++){
scanf("%lf",&r);
p.insert(0,i,log(r));
}
for(i=1;i<=n;i++){
scanf("%lf",&c);
p.insert(m+i,m+n+1,log(c));
}
for(i=1;i<=l;i++){
scanf("%d%d",&x,&y);
p.insert(x,m+y,10000.0);
}
printf("%.4lf\n",exp(p.maxFlow(0,m+n+1)));
}
void preSof(){
}
int main(){
//freopen("input.txt","r",stdin);
//freopen("output.txt","w",stdout);
preSof();
//run();
//while(~scanf("%d%d",&n,&kk)) run();
for(scanf("%d",&TS);cas<=TS;cas++) run();
return 0;
}