类似于二分匹配的构图,相乘可以用log 后相加解决
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream>
#include<cmath>
#include<stdio.h>
#include<string.h>
using namespace std;
const double inf=500.0;
const int MAX=105;
struct node
{
int v,next;
double c;
}g[100000];
int num[MAX],dis[MAX],cur[MAX],adj[MAX],pre[MAX];
int s,t,e,vn,r,c,l;
void init(int nn,int ss,int tt)
{
e=0;
memset(adj,-1,sizeof(adj));
s=ss;//源点
t=tt;//汇点
vn=nn;//vt表示总的定点数
}
void add(int u,int v,double c)
{
g[e].v=v; g[e].c=c; g[e].next=adj[u]; adj[u]=e++;
g[e].v=u; g[e].c=0; g[e].next=adj[v]; adj[v]=e++;
}
double sap()
{
int i,u,v,flag;
double aug=inf,flow=0.0;
for(i=0;i<=vn;i++)
{
dis[i]=num[i]=0;
cur[i]=adj[i];
}
u=s;
num[0]=vn;
while(dis[s]<vn)
{
flag=0;
for(i=cur[u];i!=-1;i=g[i].next)
{
v=g[i].v;
if(g[i].c>0.0&&dis[u]==dis[v]+1)
{
flag=1;
cur[u]=i;
pre[v]=u;
aug=min(aug,g[i].c);
u=v;
if(u==t)
{
flow+=aug;
//cout<<flow<<endl;
while(u!=s)
{
u=pre[u];
g[cur[u]].c-=aug;
g[cur[u]^1].c+=aug;
}
aug=inf;
}
break;
}
}
if(flag)
continue;
if(--num[dis[u]]==0)
return flow;
for(dis[u]=vn,i=adj[u];i!=-1;i=g[i].next)
{
v=g[i].v;
if(g[i].c>0.0&&dis[v]<dis[u])
{
dis[u]=dis[v];
cur[u]=i;
}
}
dis[u]++;
num[dis[u]]++;
if(u!=s)
u=pre[u];
}
return flow;
}
int main()
{
int i,j,test,a,b;
double cost;
scanf("%d",&test);
while(test--)
{
scanf("%d %d %d",&r,&c,&l);
init(r+c+2,0,r+c+1);
for(i=1;i<=r;i++)
{
scanf("%lf",&cost);
add(s,i,log(cost));
}
for(i=1;i<=c;i++)
{
scanf("%lf",&cost);
add(i+r,t,log(cost));
}
for(j=1;j<=l;j++)
{
scanf("%d %d",&a,&b);
add(a,r+b,inf);
}
// cout<<sap()<<endl;
printf("%.4lf\n",exp(sap()));
}
return 0;
}
ps:别人的模板,自己又加工了下,还是不错的