题目链接:http://poj.org/problem?id=3308
思路:裸的最小点权覆盖,建立超级源点和超级汇点,将源点与行相连,容量为这行消灭敌人的代价,将列与汇点相连,容量为这列消灭敌人的代价,对于每一个敌人(x,y),连边x->y,容量为inf,这样就说明选取的点覆盖了那些边(敌人),然后跑最大流求最小割即可。
PS:这里是乘积最小,要取对数转化为和最小。
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<queue> 6 #include<cmath> 7 using namespace std; 8 #define MAXN 222 9 #define MAXM 444444 10 #define inf 1<<30 11 12 struct Edge{ 13 int v,next; 14 double cap; 15 }edge[MAXM]; 16 17 int n,m,T,NE,NV,vs,vt; 18 int head[MAXN]; 19 20 void Insert(int u,int v,double cap) 21 { 22 edge[NE].v=v; 23 edge[NE].cap=cap; 24 edge[NE].next=head[u]; 25 head[u]=NE++; 26 27 edge[NE].v=u; 28 edge[NE].cap=0; 29 edge[NE].next=head[v]; 30 head[v]=NE++; 31 } 32 33 int level[MAXN],gap[MAXN]; 34 void bfs(int vt) 35 { 36 memset(level,-1,sizeof(level)); 37 memset(gap,0,sizeof(gap)); 38 level[vt]=0; 39 gap[level[vt]]++; 40 queue<int>que; 41 que.push(vt); 42 while(!que.empty()){ 43 int u=que.front(); 44 que.pop(); 45 for(int i=head[u];i!=-1;i=edge[i].next){ 46 int v=edge[i].v; 47 if(level[v]<0){ 48 level[v]=level[u]+1; 49 gap[level[v]]++; 50 que.push(v); 51 } 52 } 53 } 54 } 55 56 int pre[MAXN],cur[MAXN]; 57 double SAP(int vs,int vt) 58 { 59 bfs(vt); 60 memset(pre,-1,sizeof(pre)); 61 memcpy(cur,head,sizeof(head)); 62 double maxflow=0,aug=inf; 63 int u=pre[vs]=vs; 64 gap[0]=NV; 65 while(level[vs]<NV){ 66 bool flag=false; 67 for(int &i=cur[u];i!=-1;i=edge[i].next){ 68 int v=edge[i].v; 69 if(edge[i].cap>0&&level[u]==level[v]+1){ 70 flag=true; 71 pre[v]=u; 72 u=v; 73 aug=min(aug,edge[i].cap); 74 if(v==vt){ 75 maxflow+=aug; 76 for(u=pre[v];v!=vs;v=u,u=pre[u]){ 77 edge[cur[u]].cap-=aug; 78 edge[cur[u]^1].cap+=aug; 79 } 80 aug=inf; 81 } 82 break; 83 } 84 } 85 if(flag)continue; 86 int minlevel=NV; 87 for(int i=head[u];i!=-1;i=edge[i].next){ 88 int v=edge[i].v; 89 if(edge[i].cap>0&&level[v]<minlevel){ 90 minlevel=level[v]; 91 cur[u]=i; 92 } 93 } 94 if(--gap[level[u]]==0)break; 95 level[u]=minlevel+1; 96 gap[level[u]]++; 97 u=pre[u]; 98 } 99 return maxflow; 100 } 101 102 int main() 103 { 104 double x,y; 105 int _case,u,v; 106 scanf("%d",&_case); 107 while(_case--){ 108 scanf("%d%d%d",&n,&m,&T); 109 NE=0; 110 memset(head,-1,sizeof(head)); 111 vs=0,vt=n+m+1,NV=vt+1; 112 for(int i=1;i<=n;i++){ 113 scanf("%lf",&x); 114 Insert(vs,i,log(x)); 115 } 116 for(int i=1;i<=m;i++){ 117 scanf("%lf",&y); 118 Insert(i+n,vt,log(y)); 119 } 120 while(T--){ 121 scanf("%d%d",&u,&v); 122 Insert(u,v+n,inf); 123 } 124 double ans=SAP(vs,vt); 125 printf("%.4f ",exp(ans)); 126 } 127 return 0; 128 }