POJ 3308 Paratroopers

Paratroopers

Time Limit: 1000ms

Memory Limit: 65536KB

This problem will be judged on PKU. Original ID: 3308
64-bit integer IO format: %lld      Java class name: Main

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 npositive 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

Source

Amirkabir University of Technology Local Contest 2006

解题:最小点权覆盖

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <cmath>
 5 #include <algorithm>
 6 #include <climits>
 7 #include <vector>
 8 #include <queue>
 9 #include <cstdlib>
10 #include <string>
11 #include <set>
12 #include <stack>
13 #define LL long long
14 #define pii pair<int,int>
15 using namespace std;
16 const int maxn = 120;
17 const double INF = 10000.0;
18 struct arc {
19     int to,next;
20     double flow;
21     arc(int x = 0,double y = 0.0,int z = -1) {
22         to = x;
23         flow = y;
24         next = z;
25     }
26 };
27 arc e[maxn*maxn];
28 int head[maxn],d[maxn],tot,cur[maxn],S,T;
29 int n,m,k;
30 void add(int u,int v,double flow) {
31     e[tot] = arc(v,flow,head[u]);
32     head[u] = tot++;
33     e[tot] = arc(u,0.0,head[v]);
34     head[v] = tot++;
35 }
36 bool bfs() {
37     memset(d,-1,sizeof(d));
38     queue<int>q;
39     d[S] = 1;
40     q.push(S);
41     while(!q.empty()) {
42         int u = q.front();
43         q.pop();
44         for(int i = head[u]; ~i; i = e[i].next) {
45             if(e[i].flow > 0 && d[e[i].to] == -1) {
46                 d[e[i].to] = d[u] + 1;
47                 q.push(e[i].to);
48             }
49         }
50     }
51     return d[T] > -1;
52 }
53 double dfs(int u,double low) {
54     double tmp = 0,a;
55     if(u == T) return low;
56     for(int &i = cur[u]; ~i; i = e[i].next) {
57         if(e[i].flow > 0 && d[e[i].to] == d[u] + 1 && (a = dfs(e[i].to,min(e[i].flow,low)))) {
58             tmp += a;
59             low -= a;
60             e[i].flow -= a;
61             e[i^1].flow += a;
62             if(low <= 0) break;
63         }
64     }
65     if(tmp <= 0) d[u] = -1;
66     return tmp;
67 }
68 int main() {
69     double cap,ans;
70     int x,y,t;
71     scanf("%d",&t);
72     while(t--) {
73         scanf("%d %d %d",&n,&m,&k);
74         memset(head,-1,sizeof(head));
75         S = ans = tot = 0;
76         T = n + m + 1;
77         for(int i = 1; i <= n; i++) {
78             scanf("%lf",&cap);
79             add(S,i,log(cap));
80         }
81         for(int i = 1; i <= m; i++) {
82             scanf("%lf",&cap);
83             add(i+n,T,log(cap));
84         }
85         for(int i = 0; i < k; i++) {
86             scanf("%d %d",&x,&y);
87             add(x,y+n,INF);
88         }
89         ans = 0.0;
90         while(bfs()) {
91             memcpy(cur,head,sizeof(head));
92             ans += dfs(S,INF);
93         }
94         printf("%.4f\n",exp(ans));
95     }
96     return 0;
97 }

时间: 2024-10-13 21:27:04

POJ 3308 Paratroopers的相关文章

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

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

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

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

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(最大流)

1.这道题学了个单词,product 还有 乘积 的意思.. 题意就是在一个 m*n的矩阵中,放入L个敌军的伞兵,而我军要在伞兵落地的瞬间将其消灭.现在我军用一种激光枪组建一个防御系统,这种枪可以安装在一行(或者一列),并且安装在不同行(或者不同列)的费用是不一样的,枪的攻击范围是一行(或者一列).安装所有枪的费用是它们每个费用的“乘积”,现在求组建这个系统需要的最小费用. 2.与前面做的二分图的一道题有点相似(POJ - 3041 Asteroids(最小点覆盖数)).但是现在这道题在不同行(

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 infor

POJ 3308

http://poj.org/problem?id=3308 考虑答案不是乘积而是和的做法, 因为对于每一个伞兵我们要么在这行内安装大炮消灭它 要么在这列中安装大炮消灭它,所以容易看出这是一个最小边覆盖集的问题 所以转化成乘积需要用到一个特殊的方法(以前没用过) \(ans=a_1a_2\cdots a_k\) \(ans=10^{\lg ans}=10^{\lg a_1a_2\cdots a_k}\) \(ans=10^{\lg a_1+\lg a_2+\cdots \lg a_k}\) 这样

POJ 3308 最少点集覆盖

题意:和Uva 11419 类似. 首先最少点集覆盖 = 最大匹配. 我们可以在 S 和行 的边 不是1,有了权值,但是题意要求的是乘积最小,那么可以用 log(a*b) = loga + logb 转换,那么权值就是logr ,logc; 最大匹配 = 最大流(最大流一定经过最小割,最小割=最大流).那么题目就转换为求最大流了. 但是,这个题目很流氓,vector的邻接表超时,数组模拟的G++ WA,C++ AC. #include <cstdio> #include <cstring

图论常用算法之一 POJ图论题集【转载】

POJ图论分类[转] 一个很不错的图论分类,非常感谢原版的作者!!!在这里分享给大家,爱好图论的ACMer不寂寞了... (很抱歉没有找到此题集整理的原创作者,感谢知情的朋友给个原创链接) POJ:http://poj.org/ 1062* 昂贵的聘礼 枚举等级限制+dijkstra 1087* A Plug for UNIX 2分匹配 1094 Sorting It All Out floyd 或 拓扑 1112* Team Them Up! 2分图染色+DP 1125 Stockbroker