POJ #3308.Paratroopers
题面传送门
什么题目卡精度卡到人没了。
首先肯定先化乘为加,取个log
然后一个点所在的一行或一列肯定至少有一个要被选中,注意到行列分开,所以直接二分图最小点覆盖就好了。
然后你写完一个普通的网络流交上去啪的一下很快啊就WA了。
因为神奇的POJ浮点数输出%f
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<cmath>
#include<queue>
#define I inline
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define abs(x) ((x)>0?(x):-(x))
#define re register
#define RI re int
#define ll long long
#define db double
#define lb long db
#define N 100
#define M 500
#define mod 1000000007
#define Mod (mod-1)
#define eps (1e-9)
#define U unsigned int
#define it iterator
#define Gc() getchar()
#define Me(x,y) memset(x,y,sizeof(x))
#define d(x,y) (m*x+(y))
#define R(n) (rand()*rand()%(n)+1)
#define Pc(x) putchar(x)
using namespace std;
int T,n,m,k,d[N+5],Ns[N+5],x,y,Ts,S;db z,Ans;queue<int> Q;
struct yyy{int to;db w;int z;}tmp;struct ljb{int head,h[N+5];yyy f[M+5<<2];I void add(int x,int y,db z){f[head]=(yyy){y,z,h[x]};h[x]=head++;}}s;
I int bfs(){
RI i;while(!Q.empty()) Q.pop();Q.push(S);Me(d,0x3f);d[S]=0;Ns[S]=s.h[S];while(!Q.empty()) for(x=Q.front(),Q.pop(),i=s.h[x];~i;i=tmp.z){
tmp=s.f[i];if(tmp.w<eps||d[tmp.to]<1e9) continue;d[tmp.to]=d[x]+1;Q.push(tmp.to);Ns[tmp.to]=s.h[tmp.to];if(tmp.to==T) return 1;
}return 0;
}
I db dfs(int x,db sum){
if(x==T) return sum;db pus=0,k;yyy tmp;for(RI i=Ns[x];~i;i=tmp.z){
tmp=s.f[i];Ns[x]=i;if(tmp.w<eps||d[tmp.to]!=d[x]+1)continue;k=dfs(tmp.to,min(sum,tmp.w));if(k<eps) d[tmp.to]=1e9;s.f[i].w-=k;s.f[i^1].w+=k;sum-=k;pus+=k;if(sum<eps) break;
}return pus;
}
I void con(int x,int y,db z){s.add(x,y,z);s.add(y,x,0);}
I void Solve(){
Me(s.h,-1);s.head=0;RI i;scanf("%d%d%d",&n,&m,&k);S=0;T=n+m+1;for(i=1;i<=n;i++) scanf("%lf",&z),con(S,i,log2(z));for(i=1;i<=m;i++) scanf("%lf",&z),con(i+n,T,log2(z));
Ans=0;while(k--) scanf("%d%d",&x,&y),con(x,y+n,1e9);while(bfs()) Ans+=dfs(S,1e9);printf("%.4lf\n",pow(2,Ans));
}
int main(){
freopen("1.in","r",stdin);
scanf("%d",&Ts);while(Ts--) Solve();
}