POJ 3308 Paratroopers(最小割/KM)

题意:一个矩阵,有的方格里有一些敌人,每行或每列都可以安放一架枪,每架枪都有一个花费,而且能消灭他所在的行或列的所有敌人,最后的花费为所有的枪话费的乘积

分析:如果是至少安放几个枪的话,直接就是最小点覆盖;如果求和最小的话,KM就可以解决,但是球的是product 乘积。。。

       log(x)就可以转成求和了。。。用最小割或KM均可

dinic代码:

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#define inf 99999
#define nMAX 150
using namespace std;
int head[nMAX],level[nMAX],qu[nMAX],s_edge,s,t;
struct Edge
{
    int u,v,nxt;
    double w;
}edge[10000];
void addedge(int u,int v,double w)
{
    s_edge++;
    edge[s_edge].u=u;
    edge[s_edge].v=v;
    edge[s_edge].w=w;
    edge[s_edge].nxt=head[u];
    head[u]=s_edge;

    s_edge++;
    edge[s_edge].u=v;
    edge[s_edge].v=u;
    edge[s_edge].w=0;
    edge[s_edge].nxt=head[v];
    head[v]=s_edge;
}

double dinic()
{
    int beg,tail,e;
    double ans=0.0;
    while(1)
    {
        beg=tail=0;
        qu[tail++]=s;
        memset(level,-1,sizeof(level));
        level[s]=0;
        while(beg<tail)
        {
            int u=qu[beg++];
           for(e=head[u];e;e=edge[e].nxt)
            {
                int v=edge[e].v;
                if(level[v]==-1&&edge[e].w>0)
                {
                    level[v]=level[u]+1;
                    qu[tail++]=v;
                    if(v==t)
                    {
                        beg=tail;break;
                    }
                }
            }
        }
        if(level[t]==-1)break;
        beg=s,tail=0;
        while(1)
        {
            if(beg==t)
            {
                double flow=(double)inf;
                int mark;
                for(int i=0;i<tail;i++)
                    if(edge[qu[i]].w<flow)
                        mark=i,flow=edge[qu[i]].w;
                for(int i=0;i<tail;i++)
                {
                    edge[qu[i]].w-=flow;
                    edge[qu[i]^1].w+=flow;
                }
                ans+=flow;
                tail=mark;
                beg=edge[qu[mark]].u;
            }
            for(e=head[beg];e;e=edge[e].nxt)
            {
                int v=edge[e].v;
                if(level[v]==level[beg]+1&&edge[e].w>0)
                    break;
            }
            if(e)
            {
                qu[tail++]=e;
                beg=edge[e].v;
            }
            else
            {
                if(tail==0)break;
                level[edge[qu[--tail]].v]=-1;
                beg=edge[qu[tail]].u;
            }
        }
    }
    return ans;
}
int main()
{
    int CASE,i,j,k,r,c,num;
    double w;
    scanf("%d",&CASE);
    while(CASE--)
    {
        scanf("%d%d%d",&r,&c,&num);
        s_edge=1;
        memset(head,0,sizeof(head));
        s=0,t=r+c+1;
        for(i=1;i<=r;i++)
        {
            scanf("%lf",&w);
            addedge(s,i,log(w));
        }
        for(i=1;i<=c;i++)
        {
            scanf("%lf",&w);
            addedge(r+i,t,log(w));
        }
        for(i=1;i<=num;i++)
        {
            scanf("%d%d",&j,&k);
            addedge(j,r+k,double(inf));
        }
        double ans=dinic();
        printf("%.4f\n",exp(ans));//my god,G++输出写成f,毛病真多,以后都用f吧
    }
    return 0;
}

  

posted @ 2012-08-18 17:41  快乐.  阅读(144)  评论(0编辑  收藏  举报