应用到:最小割等于最大流定理
技巧:割边的乘积最小,用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; }