zoukankan      html  css  js  c++  java
  • POJ 3308 Paratroopers

    POJ_3308

    这个题目有点像二分图最小点集覆盖问题,但由于边带权,所以不能直接用二分图最大匹配来做。

    参考了别人的想法之后,发现构图的时候原来还是要用的二分图的思想,将行、列分别看做一个集合,由于最后求费用乘积的最小值,所以先传化成log2形式的费用,源点与行之间的容量初始化为log2行费用,列与汇点之间的容量初始化log2列费用。之后对读入的伞兵位置对应的行和列之间连一条有向边,容量为INF

        最后只要求一下最小割就可以了,也就是最大网络流。

    #include<stdio.h>
    #include
    <string.h>
    #include
    <math.h>
    double cap[110][110],flow[110][110],a[110];
    int q[110],p[110];
    int main()
    {
    int i,j,k,n,m,l,T,t,u,v,front,rear;
    double f,temp;
    scanf(
    "%d",&T);
    while(T--)
    {
    scanf(
    "%d%d%d",&m,&n,&l);
    t
    =m+n+1;
    for(i=0;i<=t;i++)
    for(j=0;j<=t;j++)
    {
    cap[i][j]
    =0.0;
    flow[i][j]
    =0.0;
    }
    for(i=1;i<=m;i++)
    {
    scanf(
    "%lf",&temp);
    cap[
    0][i]=log2(temp);
    }
    for(i=m+1;i<t;i++)
    {
    scanf(
    "%lf",&temp);
    cap[i][t]
    =log2(temp);
    }
    for(i=0;i<l;i++)
    {
    scanf(
    "%d%d",&u,&v);
    cap[u][m
    +v]=1000000000.0;
    }
    f
    =0;
    while(1)
    {
    for(i=1;i<=t;i++)
    a[i]
    =0.0;
    a[
    0]=1000000000.0;
    front
    =rear=0;
    q[rear
    ++]=0;
    while(front<rear)
    {
    u
    =q[front++];
    for(v=0;v<=t;v++)
    if(a[v]<1e-8&&cap[u][v]>flow[u][v])
    {
    temp
    =cap[u][v]-flow[u][v];
    a[v]
    =a[u]<temp?a[u]:temp;
    p[v]
    =u;
    q[rear
    ++]=v;
    }
    }
    if(a[t]<1e-8)
    break;
    for(u=t;u!=0;u=p[u])
    {
    flow[p[u]][u]
    +=a[t];
    flow[u][p[u]]
    -=a[t];
    }
    f
    +=a[t];
    }
    printf(
    "%.4f\n",pow(2,f));
    }
    return 0;
    }
  • 相关阅读:
    Windows系统的DOS常用命令
    常用pom
    ssm整合
    pom依赖集合
    json
    软件项目管理笔记-软件项目计划
    CSS
    网络配置
    用户组
    用户管理
  • 原文地址:https://www.cnblogs.com/staginner/p/2130001.html
Copyright © 2011-2022 走看看