应用到:最小割等于最大流定理
技巧:割边的乘积最小,用log转化!!太好了!!
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
using namespace std;
int m,n,l,s,t;
#define N 120
#define M 2000
const double INF =1000000000000.0;
#define eps 1e-12
bool equal(double a,double b)
{
return fabs(a-b)<eps;
}
struct Edge
{
int v;
double w;
}edge[M];
int adj[M],head[N],e;
int q[N*2],front,rear,vis[N],gap[N],arc[N],dist[N],pre[N];
double sap(int s,int t)
{
memset(vis,0,sizeof(vis));
memset(gap,0,sizeof(gap));
memset(pre,-1,sizeof(pre));
memset(arc,-1,sizeof(arc));
front=rear=0;
q[rear++]=t;dist[t]=0;gap[0]++;vis[t]=1;
while(front<rear)
{
int u=q[front++];
for(int i=head[u];i!=-1;i=adj[i])
if(!vis[edge[i].v])
{
q[rear++]=edge[i].v;
vis[edge[i].v]=1;
arc[edge[i].v]=head[edge[i].v];
dist[edge[i].v]=dist[u]+1;
gap[dist[edge[i].v]]++;
}
}
double ans=0.0;
int u=s;double low=INF-1;pre[s]=s;
while(dist[s]<m+n+2)
{
bool flag=false;
for(int &i=arc[u];i!=-1;i=adj[i])
if(!equal(edge[i].w,0.0) && dist[u]==dist[edge[i].v]+1)
{
flag=true;
low=min(low,edge[i].w);
pre[edge[i].v]=u;
u=edge[i].v;
if(u==t)
{
while(u!=s)
{
u=pre[u];
edge[arc[u]].w-=low;
edge[arc[u]^1].w+=low;
}
ans+=low;
low=INF-1;
}
break;
}
if(flag)
continue;
int mindist=m+n+2;
for(int i=head[u];i!=-1;i=adj[i])
if(!equal(edge[i].w,0.0) && mindist>dist[edge[i].v])
{
arc[u]=i;
mindist=dist[edge[i].v];
}
gap[dist[u]]--;
if(gap[dist[u]]==0)
break;
dist[u]=mindist+1;
gap[dist[u]]++;
u=pre[u];
}
return ans;
}
void addedge(int u,int v,double w)
{
edge[e].v=v;edge[e].w=w;adj[e]=head[u];head[u]=e++;
edge[e].v=u;edge[e].w=0;adj[e]=head[v];head[v]=e++;
}
void init()
{
e=0;s=0;t=m+n+1;
memset(head,-1,sizeof(head));
}
int main ()
{
int test;scanf("%d",&test);
while(test--)
{
scanf("%d%d%d",&m,&n,&l);
init();
double temp;
for(int i=1;i<=m;++i)
{
scanf("%lf",&temp);
addedge(s,i,log(temp));
}
for(int i=m+1;i<=m+n;++i)
{
scanf("%lf",&temp);
addedge(i,t,log(temp));
}
int u,v;
while(l--)
{
scanf("%d%d",&u,&v);
addedge(u,m+v,INF);
}
double ans=sap(s,t);
ans=exp(ans);
printf("%.4lf\n",ans);
}
return 0;
}