题意

敌人侵略r*c的地图。为了消灭敌人,可以在某一行或者某一列安置超级大炮。每一个大炮可以瞬间消灭这一行(或者列)的敌人。安装消灭第i行的大炮消费是ri。安装消灭第j行的大炮消费是ci现在有n个敌人,告诉你这n个敌人的坐标,让你同时消灭这些敌人,为你最小花费是多少。花费的定义:每个大炮消费的乘积。

思路

非常经典的最小点权覆盖集问题,同最大流建模就可以了,建模方法可见胡伯涛论文《最小割模型在信息学竞赛中的应用》。

这道题的模型转换成最小点权覆盖集的方法可见这里.

这里的点权最大是乘积的,只要对权值取对数就把乘法转换成加法了~~

代码

[cpp]
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <stack>
#include <queue>
#include <algorithm>
#include <string>
#include <cstring>
#define MID(x,y) ((x+y)/2)
#define MEM(a,b) memset(a,b,sizeof(a))
#define REP(i, begin, m) for (int i = begin; i < begin+m; ++ i)
using namespace std;
const int MAXV = 1005;
const int MAXE = 1005;
const int oo = 0x3fffffff;

template
struct Dinic{
struct flow_node{
int u, v;
T flow;
int opp;
int next;
}arc[2*MAXE];
int vn, en, head[MAXV];
int cur[MAXV];
int q[MAXV];
int path[2*MAXE], top;
int dep[MAXV];
void init(int n){
vn = n;
en = 0;
MEM(head, -1);
}
void insert_flow(int u, int v, T flow){
arc[en].u = u;
arc[en].v = v;
arc[en].flow = flow;
arc[en].next = head[u];
head[u] = en ++;

arc[en].u = v;
arc[en].v = u;
arc[en].flow = 0;
arc[en].next = head[v];
head[v] = en ++;
}
bool bfs(int s, int t){
MEM(dep, -1);
int lq = 0, rq = 1;
dep[s] = 0;
q[lq] = s;
while(lq < rq){ int u = q[lq ++]; if (u == t){ return true; } for (int i = head[u]; i != -1; i = arc[i].next){ int v = arc[i].v; if (dep[v] == -1 && arc[i].flow > 0){
dep[v] = dep[u] + 1;
q[rq ++] = v;
}
}
}
return false;
}
T solve(int s, int t){
T maxflow = 0;
while(bfs(s, t)){
int i, j;
for (i = 1; i <= vn; i ++) cur[i] = head[i];
for (i = s, top = 0;;){
if (i == t){
int mink;
T minflow = 0x7fffffff; //要比容量的oo大
for (int k = 0; k < top; k ++) if (minflow > arc[path[k]].flow){
minflow = arc[path[k]].flow;
mink = k;
}
for (int k = 0; k < top; k ++)
arc[path[k]].flow -= minflow, arc[path[k]^1].flow += minflow;
maxflow += minflow;
top = mink;
i = arc[path[top]].u;
}
for (j = cur[i]; j != -1; cur[i] = j = arc[j].next){
int v = arc[j].v;
if (arc[j].flow && dep[v] == dep[i] + 1)
break;
}
if (j != -1){
path[top ++] = j;
i = arc[j].v;
}
else{
if (top == 0) break;
dep[i] = -1;
i = arc[path[-- top]].u;
}
}
}
return maxflow;
}
};
Dinic dinic;
double r[55], c[55];

int main(){
//freopen("test.in", "r", stdin);
//freopen("test.out", "w", stdout);
int n, m, l;
int t;
scanf("%d", &t);
while(t --){
scanf("%d %d %d", &n, &m, &l);
dinic.init(n+m+2);
REP(i, 1, n){
scanf("%lf", &r[i]);
dinic.insert_flow(n+m+1, i, log(r[i]));
}
REP(i, 1, m){
scanf("%lf", &c[i]);
dinic.insert_flow(i+n, n+m+2, log(c[i]));
}

REP(i, 1, l){
int u, v;
scanf("%d %d", &u, &v);
dinic.insert_flow(u, v+n, oo);
}
printf("%.4f\n", exp(dinic.solve(n+m+1, n+m+2)));
}
return 0;
}
[/cpp]

POJ 3308 Paratroopers (对数转换+最小点权覆盖)的更多相关文章

  1. poj 3308 Paratroopers(二分图最小点权覆盖)

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

  2. POJ - 2125 Destroying The Graph (最小点权覆盖)

    题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...

  3. poj3308 Paratroopers 最大流 最小点权覆盖

    题意:有一个n*m的矩阵,告诉了在每一行或者每一列安装大炮的代价,每一个大炮可以瞬间消灭这一行或者这一列的所有敌人,然后告诉了敌人可能出现的L个坐标位置,问如何安置大炮,使花费最小.如果一个敌人位于第 ...

  4. POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)

    http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...

  5. POJ - 3308 Paratroopers (最小点权覆盖)

    题意:N*M个格点,K个位置会有敌人.每行每列都有一门炮,能打掉这一行(列)上所有的敌人.每门炮都有其使用价值.总花费是所有使用炮的权值的乘积.求最小的总花费. 若每门炮的权值都是1,就是求最小点覆盖 ...

  6. POJ 3308 Paratroopers(最大流最小割の最小点权覆盖)

    Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...

  7. poj 3308(最小点权覆盖、最小割)

    题目链接:http://poj.org/problem?id=3308 思路:裸的最小点权覆盖,建立超级源点和超级汇点,将源点与行相连,容量为这行消灭敌人的代价,将列与汇点相连,容量为这列消灭敌人的代 ...

  8. POJ - 3308 Paratroopers(最大流)

    1.这道题学了个单词,product 还有 乘积 的意思.. 题意就是在一个 m*n的矩阵中,放入L个敌军的伞兵,而我军要在伞兵落地的瞬间将其消灭.现在我军用一种激光枪组建一个防御系统,这种枪可以安装 ...

  9. POJ3308 Paratroopers(最小割/二分图最小点权覆盖)

    把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...

随机推荐

  1. POJ 1305 Fermat vs. Pythagoras (毕达哥拉斯三元组)

    设不定方程:x^2+y^2=z^2若正整数三元组(x,y,z)满足上述方程,则称为毕达哥拉斯三元组.若gcd(x,y,z)=1,则称为本原的毕达哥拉斯三元组. 定理:正整数x,y,z构成一个本原的毕达 ...

  2. 传说中的WCF(12):服务器回调有啥用

    你说,服务器端回调有啥用呢?这样问,估计不好回答,是吧.不急,先讨论一个情景. 假设现有服务器端S,客户端A开始连接S并调用相关操作,其中有一个操作,在功能上有些特殊,调用后无法即时回复,因为在服务器 ...

  3. (7)nehe教程1 创建一个OpenGL窗口:

    不要用那个nehe ndk了 误人子弟! 转自: 一个窗口,代码可真多啊 http://www.yakergong.net/nehe/ 在这个教程里,我将教你在Windows环境中创建OpenGL程序 ...

  4. node中的模块

    模块 编写稍大一点的程序时一般都会将代码模块化.在NodeJS中,一般将代码合理拆分到不同的JS文件中,每一个文件就是一个模块,而文件路径就是模块名. 在编写每个模块时,都有require.expor ...

  5. unity3d设置3D模型显示在2D背景之前(多个相机分层显示)(转)

    解决步骤: 1.添加一个摄像机,命名为BackgroundCamera,然后在Layer添加一个background层.并且将plane拖放到改相机节点下. 然后将BackgroundCamera和P ...

  6. java--vo

    VO是跟数据库里表的映射,一个表对应一个VO DAO是用VO来访问真实的表,对数据库的操作都在DAO中完成 BO是业务层,做逻辑处理的 VO , PO , BO , QO, DAO ,POJO, O/ ...

  7. STM32的GPIO口的输出开漏输出和推挽输出

    本文来自cairang45的博客,讲述了STM32的GPIO口的输出开漏输出和推挽输出, 作者博客:http://blog.ednchina.com/cairang45 本文来自: 高校自动化网(Ww ...

  8. PO/POJO/VO/BO/DAO/DTO

    PO(persistant object) 持久对象在o/r 映射的时候出现的概念,如果没有o/r映射,就没有这个概念存在了.通常对应数据模型(数据库),本身还有部分业务逻辑的处理.可以看成是与数据库 ...

  9. hive-0.12升级成hive 0.13.1

    安装了0.12之后,听说0.13.1有许多新的特性,包括永久函数,所以想更新成0.13版的(元数据放在mysql中) 2014年8月5日实验成功 hive0.13.1的新特性 新特性详见 http:/ ...

  10. linux read和write函数

    原文出处:http://blog.chinaunix.net/space.php?uid=20558494&do=blog&id=2803003read函数是Linux下不带缓存的文件 ...