poj 3308 Paratroopers(最小点权覆盖)

Paratroopers

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 8954   Accepted: 2702

Description

It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the Mars. Recently, the commanders of the Earth are informed by their spies that the invaders of Mars want to land some paratroopers in the × n grid yard of one their main weapon factories in order to destroy it. In addition, the spies informed them the row and column of the places in the yard in which each paratrooper will land. Since the paratroopers are very strong and well-organized, even one of them, if survived, can complete the mission and destroy the whole factory. As a result, the defense force of the Earth must kill all of them simultaneously after their landing.

In order to accomplish this task, the defense force wants to utilize some of their most hi-tech laser guns. They can install a gun on a row (resp. column) and by firing this gun all paratroopers landed in this row (resp. column) will die. The cost of installing a gun in the ith row (resp. column) of the grid yard is ri (resp. ci ) and the total cost of constructing a system firing all guns simultaneously is equal to the product of their costs. Now, your team as a high rank defense group must select the guns that can kill all paratroopers and yield minimum total cost of constructing the firing system.

Input

Input begins with a number T showing the number of test cases and then, T test cases follow. Each test case begins with a line containing three integers 1 ≤ m ≤ 50 , 1 ≤ n ≤ 50 and 1 ≤ l ≤ 500 showing the number of rows and columns of the yard and the number of paratroopers respectively. After that, a line with m positive real numbers greater or equal to 1.0 comes where the ith number is ri and then, a line with n positive real numbers greater or equal to 1.0 comes where the ith number is ci. Finally, l lines come each containing the row and column of a paratrooper.

Output

For each test case, your program must output the minimum total cost of constructing the firing system rounded to four digits after the fraction point.

Sample Input

1
4 4 5
2.0 7.0 5.0 2.0
1.5 2.0 2.0 8.0
1 1
2 2
3 3
4 4
1 4

Sample Output

16.0000

二分图的最小点权覆盖。

code

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 #include<cmath>
 5
 6 using namespace std;
 7
 8 const int N = 5010;
 9 const double INF = 1000000000.0;
10 const double eps = 1e-10;
11 struct Edge{
12     int to,nxt;double c;
13     Edge() {}
14     Edge(int x,double y,int z) {to = x,c = y,nxt = z;}
15 }e[100100];
16 int q[100100],L,R,S,T,tot = 1;
17 int dis[N],cur[N],head[N];
18
19 void add_edge(int u,int v,double c) {
20     e[++tot] = Edge(v,c,head[u]);head[u] = tot;
21     e[++tot] = Edge(u,0,head[v]);head[v] = tot;
22 }
23 bool bfs() {
24     for (int i=1; i<=T; ++i) cur[i] = head[i],dis[i] = -1;
25     L = 1,R = 0;
26     q[++R] = S;dis[S] = 0;
27     while (L <= R) {
28         int u = q[L++];
29         for (int i=head[u]; i; i=e[i].nxt) {
30             int v = e[i].to;
31             if (dis[v] == -1 && e[i].c > eps) {
32                 dis[v] = dis[u]+1;q[++R] = v;
33                 if (v==T) return true;
34             }
35         }
36     }
37     return false;
38 }
39 double dfs(int u,double flow) {
40     if (u==T) return flow;
41     double used = 0;
42     for (int &i=cur[u]; i; i=e[i].nxt) {
43         int v = e[i].to;
44         if (dis[v] == dis[u] + 1 && e[i].c > eps) {
45             double tmp = dfs(v,min(flow-used,e[i].c));
46             if (tmp > eps) {
47                 e[i].c -= tmp;e[i^1].c += tmp;
48                 used += tmp;
49                 if (used == flow) break;
50             }
51         }
52     }
53     if (used != flow) dis[u] = -1;
54     return used;
55 }
56 double dinic() {
57     double ret = 0.0;
58     while (bfs()) ret += dfs(S,INF);
59     return ret;
60 }
61 void Clear() {
62     tot = 1;
63     memset(head,0,sizeof(head));
64 }
65 int main() {
66     int Case,n,m,E,u,v;double x;
67     scanf("%d",&Case);
68     while (Case--) { //-不要设T
69         Clear();
70         scanf("%d%d%d",&n,&m,&E);
71         S = n+m+1;T = n+m+2;
72         for (int i=1; i<=n; ++i) {
73             scanf("%lf",&x);
74             add_edge(S,i,log(x));
75         }
76         for (int i=1; i<=m; ++i) {
77             scanf("%lf",&x);
78             add_edge(i+n,T,log(x));
79         }
80         for (int i=1; i<=E; ++i) {
81             scanf("%d%d",&u,&v);
82             add_edge(u,v+n,INF);
83         }
84         double ans = dinic();
85         printf("%.4lf\n",exp(ans));
86     }
87     return 0;
88 }

原文地址:https://www.cnblogs.com/mjtcn/p/8545196.html

时间: 2024-08-02 01:32:16

poj 3308 Paratroopers(最小点权覆盖)的相关文章

POJ 3308 Paratroopers 最小点权覆盖 求最小割

不懂这个建模是什么原理,以后把二分图相关的东西看完再补上把= = #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #i

poj3308 Paratroopers --- 最小点权覆盖-&gt;最小割

题目是一个很明显的二分图带权匹配模型, 添加源点到nx建边,ny到汇点建边,(nx,ny)=inf建边,求最小割既得最小点权覆盖. 在本题中由于求的是乘积,所以先全部取log转换为加法,最后再乘方回来. #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #inc

zoj 2874 &amp; poj 3308 Paratroopers (最小割)

题意: 一个m*n大小的网格,已知伞兵着陆的具体位置(行和列).现在在某行(或某列) 安装一架激光枪,一架激光枪能杀死该行(或该列)所有的伞兵.在第i行安装一架 激光枪的费用是Ri,在第i列安装的费用是Ci.要安装整个激光枪系统,总费用为这些 激光枪费用的乘积. 求杀死所有伞兵的最小费用. 构图: 把伞兵视为边,行与列视为顶点.增加源点和汇点,对于第i行,从源点向顶点i连接一条 容量为Ri的边.对于第j列,从顶点j向汇点连接一条容量为Rj的边. 如果某一点(i,j)有伞兵降落,则从顶点Ri向顶点

poj 3308 Paratroopers 最小割 最小点权覆盖

题目链接:http://poj.org/problem?id=3308 题意: 有一个M*N的图,上面的一些点上有伞兵. 可以设置一些枪在每行或者每列上,通过射击,这行或这列的伞兵就会被消灭.每个枪的设置有一个花费,如果设置多个枪,那么花费是设置每个枪的乘积. 问消灭所有伞兵最少的花费是多少. 思路: 每个点的伞兵至少要用那一列或者那一行设置的枪去消灭,那么就可以应用点覆盖的模型.把伞兵看成是一条边,这条边至少要用一个点来覆盖. 而题目中最终花费是所有花费的乘积,那么可以用对数log(x)+lo

POJ 3308--Paratroopers【 最小点权覆盖 &amp;&amp; 最小割】

Paratroopers Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7847   Accepted: 2365 Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the Mars. Recently, the commanders of the Earth are infor

poj3308 Paratroopers --- 最小点权覆盖-&amp;gt;最小割

题目是一个非常明显的二分图带权匹配模型, 加入源点到nx建边,ny到汇点建边,(nx.ny)=inf建边.求最小割既得最小点权覆盖. 在本题中因为求的是乘积,所以先所有取log转换为加法,最后再乘方回来. #include <iostream> #include <cstring> #include <string> #include <cstdio> #include <cmath> #include <algorithm> #in

POJ 3308 Paratroopers (二分图最小点权覆盖 -&gt; 最小割 -&gt; 最大流)

POJ 3308 Paratroopers 链接:http://poj.org/problem?id=3308 题意:有一个N*M的方阵,有L个伞兵降落在方阵上.现在要将所有的伞兵都消灭掉,可以在每行每列装一个高射炮,如果在某行(某列)装上高射炮之后,能够消灭所有落在该行(该列)的伞兵.每行每列安高射炮有费用,问如何安装能够使得费用之积最小. 思路:首先题目要求乘积最小,将乘积对e取对数,会发现就变成了求和.然后抽象出一个二分图,每一行是x部的一个点,每个点有权值,权值为费用取ln.每一列是y部

POJ3308 Paratroopers(最小割/最小点权覆盖)

把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运算,最后再还原. 另外还可以从最小割的思路去这么理解: 每一行与源点相连,容量为该行的花费:每一列与汇点相连,容量为该列的花费:对于每个入侵者的坐标,该行该列连接一条容量INF的边. 要让源点汇点不连通,割边集必然与所有入侵者的行或列相关,而这样建模后的最小割就是最小的花费(容量INF的边必然不是最

POJ 2125 Destroying the Graph 二分图最小点权覆盖

Destroying The Graph Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 8198   Accepted: 2635   Special Judge Description Alice and Bob play the following game. First, Alice draws some directed graph with N vertices and M arcs. After that B