zoukankan      html  css  js  c++  java
  • poj 3308 Paratroopers 最小割 最小点权覆盖

    题目链接:http://poj.org/problem?id=3308

    题意:

    有一个M*N的图,上面的一些点上有伞兵。

    可以设置一些枪在每行或者每列上,通过射击,这行或这列的伞兵就会被消灭。每个枪的设置有一个花费,如果设置多个枪,那么花费是设置每个枪的乘积。

    问消灭所有伞兵最少的花费是多少。

    思路:

    每个点的伞兵至少要用那一列或者那一行设置的枪去消灭,那么就可以应用点覆盖的模型。把伞兵看成是一条边,这条边至少要用一个点来覆盖。

    而题目中最终花费是所有花费的乘积,那么可以用对数log(x)+log(y) = log(x*y)来转换。

    所以就可以用最小点权覆盖模型来解决。

    设置一个超级源点s和超级汇点t。

    s向每行连一条边,容量是log(在这些行设置枪的花费)。

    每列向t连一条边,容量是log(在这些列设置枪的花费)。

    对于每个伞兵所在的位置(x, y),则x向y连一条边,容量是inf。

    然后求最小割。答案就是exp(最大流)。

    这题要注意一下精度问题,esp开1e-8,因为保留4位小数。用G++时,双精度是%f,用C++时双精度是%lf。

      1 //#include <bits/stdc++.h>
      2 #include <iostream>
      3 #include <cstring>
      4 #include <cstdio>
      5 #include <cmath>
      6 #include <queue>
      7 #include <vector>
      8 using namespace std;
      9 struct Edge
     10 {
     11     int from, to; double cap, flow;
     12     Edge(int f, int t, double c, double fl)
     13     {
     14         from = f; to = t; cap = c; flow = fl;
     15     }
     16 };
     17 #define maxn 110
     18 #define inf 100000
     19 #define eps 1e-8
     20 int n, m, s, t;
     21 vector <Edge> edges;
     22 vector <int> G[maxn];
     23 int d[maxn], cur[maxn], vis[maxn];
     24 void AddEdge(int from, int to, double cap)
     25 {
     26     edges.push_back(Edge(from, to, cap, 0));
     27     edges.push_back(Edge(to, from, 0, 0));
     28     m = edges.size();
     29     G[from].push_back(m-2);
     30     G[to].push_back(m-1);
     31 }
     32 bool bfs()
     33 {
     34     memset(vis, 0, sizeof(vis));
     35     d[s] = 0; vis[s] = 1;
     36     queue <int> q; q.push(s);
     37     while(!q.empty())
     38     {
     39         int x = q.front(); q.pop();
     40         for(int i = 0; i < G[x].size(); i++)
     41         {
     42             Edge &e = edges[G[x][i]];
     43             if(!vis[e.to] && e.cap > e.flow)
     44             {
     45                 d[e.to] = d[x] + 1;
     46                 vis[e.to] = 1;
     47                 q.push(e.to);
     48             }
     49         }
     50     }
     51     return vis[t];
     52 }
     53 double dfs(int x, double a)
     54 {
     55     if(x == t || fabs(a) < eps) return a;
     56     double flow = 0, f;
     57     for(int &i = cur[x]; i < G[x].size(); i++)
     58     {
     59         Edge &e = edges[G[x][i]];
     60         if(d[e.to] == d[x] + 1 && (f = dfs(e.to, min(a, e.cap - e.flow))) > 0)
     61         {
     62             e.flow += f;
     63             edges[G[x][i]^1].flow -= f;
     64             flow += f;
     65             a -= f;
     66             if(fabs(a) < eps) break;
     67         }
     68     }
     69     return flow;
     70 }
     71 double maxflow()
     72 {
     73     double flow = 0;
     74     while(bfs())
     75     {
     76         memset(cur, 0, sizeof(cur));
     77         flow += dfs(s, inf);
     78     } 
     79     return flow;
     80 }
     81 int T, M, N, L;
     82 int main() 
     83 {
     84     //freopen("in.txt", "r", stdin);
     85     //freopen("out.txt", "w", stdout);
     86     scanf("%d", &T);
     87     while(T--)
     88     {
     89         scanf("%d%d%d",  &M, &N, &L);
     90         edges.clear();
     91         s = 0; t = N+M+1; n = N+M+2;
     92         for(int i = s; i <= t; i++) G[i].clear();
     93         double val;
     94         for(int i = 1; i <= M; i++)
     95         {
     96             scanf("%lf", &val);
     97             AddEdge(s, i, log(val));
     98         }
     99         for(int i = 1; i <= N; i++)
    100         {
    101             scanf("%lf", &val);
    102             AddEdge(i+M, t, log(val));
    103         }
    104         for(int i = 1; i <= L; i++)
    105         {
    106             int a, b; scanf("%d%d", &a, &b);
    107             AddEdge(a, b+M, inf);
    108         }
    109         double flow = maxflow();
    110         printf("%.4lf
    ", exp(flow));
    111     }
    112     return 0;
    113 }
  • 相关阅读:
    【家庭记账本】Android开发日记(七)
    每日总结【2020/02/08】
    每日总结【2020/02/07】
    【家庭记账本】Android开发日记(六)
    每日总结【2020/02/06】
    【家庭记账本】Android开发日记(五)
    【iOS开发】 CoreText 使用教程:以创建一个简单的杂志应用为例
    用NSLogger代替NSLog输出调试信息
    iOS开发常用国外网站清单
    Xcode快捷键 2(转)
  • 原文地址:https://www.cnblogs.com/titicia/p/5222037.html
Copyright © 2011-2022 走看看