poj 3308 Paratroopers

来源:互联网 发布:Java国密算法 编辑:程序博客网 时间:2024/04/29 08:52
题意:在一个矩阵中某些坐标点存在你的敌人,现有一些炮弹,他们可以摆在任意一行或者任意一列,并且可以消灭掉一行或者一列上的敌人。要求消灭掉所都敌人需要的最小花费。最小点覆盖:建立超级源点和每行连接,权值为放在该行炮弹的花费。建立超级汇点和每列连接,权值为放在该列炮弹的花费。存在敌人的行和列之间连一条边,权值为inf。跑一遍最小割。#include<cmath>#include<stdio.h>#include<string.h>#include<iostream>#define inf 10000000using namespace std;struct node{int u,v,next;double c;}edge[1200];int head[1200],pre[1200],cur[1200],dis[1200],gap[1200];double flow[1200],a[1200],b[1200];int T,m,n,l,x,y,e,start,end;double ans,tot;void add_adge(int u,int v,double c){    edge[e].u=u;  edge[e].v=v;  edge[e].c=c;  edge[e].next=head[u]; head[u]=e++;    edge[e].u=v;  edge[e].v=u;  edge[e].c=0;  edge[e].next=head[v]; head[v]=e++;}double sap()  {       double flow=0,aug=inf;      bool flag; int u;    for(int i=0; i<=n+m+1; i++)      {          cur[i]=head[i];          gap[i]=dis[i]=0;      }      gap[start]=n+m+2;       u=pre[start]=start;     while(dis[start]<n+m+2)      {          flag=0;          for(int &j=cur[u]; j!=-1; j=edge[j].next)          {              int v=edge[j].v;              if(edge[j].c>0&&dis[u]==dis[v]+1)              {                  flag=1;                  if(edge[j].c<aug) aug=edge[j].c;                  pre[v]=u;                  u=v;                  if(u==n+m+1)                  {                      flow+=aug;                      while(u!=0)                      {                          u=pre[u];                          edge[cur[u]].c-=aug;                          edge[cur[u]^1].c+=aug;                      }                      aug=inf;                  }                  break;              }          }         if(flag) continue;          int mindis=n+m+2;          for(int j=head[u]; j!=-1; j=edge[j].next)          {              int v=edge[j].v;              if(edge[j].c>0&&dis[v]<mindis)              {                  mindis=dis[v];                  cur[u]=j;              }          }          if((--gap[dis[u]])==0)              break;          gap[dis[u]=mindis+1]++;          u=pre[u];      }      return flow;  }  int main(){    scanf("%d",&T);    while(T--)    {       scanf("%d%d%d",&m,&n,&l);       e=0;start=0,end=n+m+1;       memset(head,-1,sizeof(head));       for(int i=1;i<=m;i++)       {          scanf("%lf",&a[i]);          add_adge(0,i,log(a[i]));       }       for(int i=1;i<=n;i++)       {           scanf("%lf",&b[i]);          add_adge(m+i,m+n+1,log(b[i]));       }       for(int i=1;i<=l;i++)       {          scanf("%d%d",&x,&y);          add_adge(x,m+y,inf);       }       printf("%.4lf\n",exp(sap()));     }     return 0;}