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

    题意:火星人要攻打地球,火星人将派来一些伞兵来破坏军事设施。已知他们将降落在一个矩阵行的地区,而且知道这些人会降落在哪一行那一列。现在地球人可以造一些大炮来攻击他们,一门大炮可以攻击一行或者一列,一个伞兵只要被他所在的行或列的大炮打中他就会挂,而在每一行、每一列造大炮的价格是不同的,建造大炮总价格等于你选择在某行或某列造大炮价格的乘积。现在要求把所有的伞兵都搞挂了并且让这个价格尽可能的小。

    看到乘积尽量小,想到了取对数。那么剩下的问题就是二分图点权覆盖的问题了。最后求完最大流之后,再还原这个费用就可以了。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <cmath>
     4 #include <algorithm>
     5 using namespace std;
     6 const int maxn = 110;
     7 const int maxm = 10000;
     8 const double inf = 1e8;
     9 int v[maxm],next[maxm];
    10 double w[maxm];
    11 int first[maxn],d[maxn],work[maxn],q[maxn];
    12 int e,S,T;
    13 
    14 void init(){
    15     e = 0;
    16     memset(first,-1,sizeof(first));
    17 }
    18 
    19 void add_edge(int a,int b,double c){
    20     //printf("add:%d to %d,cap = %.4f
    ",a,b,c);
    21     v[e] = b;next[e] = first[a];w[e] = c;first[a] = e++;
    22     v[e] = a;next[e] = first[b];w[e] = 0;first[b] = e++;
    23 }
    24 
    25 int bfs(){
    26     int rear = 0;
    27     memset(d,-1,sizeof(d));
    28     d[S] = 0;q[rear++] = S;
    29     for(int i = 0;i < rear;i++){
    30         for(int j = first[q[i]];j != -1;j = next[j])
    31             if(w[j] && d[v[j]] == -1){
    32                 d[v[j]] = d[q[i]] + 1;
    33                 q[rear++] = v[j];
    34                 if(v[j] == T)   return 1;
    35             }
    36     }
    37     return 0;
    38 }
    39 
    40 double dfs(int cur,double a){
    41     if(cur == T)    return a;
    42     for(int &i = work[cur];i != -1;i = next[i]){
    43         if(w[i] && d[v[i]] == d[cur] + 1)
    44             if(double t = dfs(v[i],min(a,w[i]))){
    45                 w[i] -= t;w[i^1] += t;
    46                 return t;
    47             }
    48     }
    49     return 0;
    50 }
    51 
    52 double dinic(){
    53     double ans = 0;
    54     while(bfs()){
    55         memcpy(work,first,sizeof(first));
    56         while(double t = dfs(S,inf))    ans += t;
    57     }
    58     return ans;
    59 }
    60 
    61 int main()
    62 {
    63     int kase,m,n,l;
    64     scanf("%d",&kase);
    65     while(kase--){
    66         init();
    67         scanf("%d%d%d",&m,&n,&l);
    68         S = 0,T = m+n+1;
    69         for(int i = 1;i <= m;i++){
    70             double c;
    71             scanf("%lf",&c);
    72             add_edge(S,i,log(c));
    73         }
    74         for(int i = m+1;i <= m+n;i++){
    75             double c;
    76             scanf("%lf",&c);
    77             add_edge(i,T,log(c));
    78         }
    79         for(int i = 0;i < l;i++){
    80             int a,b;
    81             scanf("%d%d",&a,&b);
    82             add_edge(a,b+m,inf);
    83         }
    84         double ans = dinic();
    85         printf("%.4f
    ",exp(ans));
    86     }
    87     return 0;
    88 }
    View Code
  • 相关阅读:
    我的博客园的博客开通啦
    设置cookie
    JavaScript自动提示
    补码
    vim快捷键
    JavaScript获取URL参数
    Linux根目录下子目录的功能
    JavaScript分页栏链接转变算法
    可输可选可自动提示,还可增加一个!
    VS2008启动调试,出现“ 已经找到网站 正在等待回应”
  • 原文地址:https://www.cnblogs.com/zhexipinnong/p/3420088.html
Copyright © 2011-2022 走看看