POJ 3308 Paratroopers (对数转换+最小点权覆盖)
题意
敌人侵略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 (对数转换+最小点权覆盖)的更多相关文章
- poj 3308 Paratroopers(二分图最小点权覆盖)
Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8954 Accepted: 2702 Desc ...
- POJ - 2125 Destroying The Graph (最小点权覆盖)
题意:给一张图,现在要删去所有的边,删去一个点的所有入边和所有出边都有其对应\(W_{i+}\)和\(W_{i-}\).求删去该图的最小花费,并输出解 分析:简而言之就是用最小权值的点集去覆盖所有的边 ...
- poj3308 Paratroopers 最大流 最小点权覆盖
题意:有一个n*m的矩阵,告诉了在每一行或者每一列安装大炮的代价,每一个大炮可以瞬间消灭这一行或者这一列的所有敌人,然后告诉了敌人可能出现的L个坐标位置,问如何安置大炮,使花费最小.如果一个敌人位于第 ...
- POJ 3308 Paratroopers(最小点权覆盖)(对数乘转加)
http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...
- POJ - 3308 Paratroopers (最小点权覆盖)
题意:N*M个格点,K个位置会有敌人.每行每列都有一门炮,能打掉这一行(列)上所有的敌人.每门炮都有其使用价值.总花费是所有使用炮的权值的乘积.求最小的总花费. 若每门炮的权值都是1,就是求最小点覆盖 ...
- POJ 3308 Paratroopers(最大流最小割の最小点权覆盖)
Description It is year 2500 A.D. and there is a terrible war between the forces of the Earth and the ...
- poj 3308(最小点权覆盖、最小割)
题目链接:http://poj.org/problem?id=3308 思路:裸的最小点权覆盖,建立超级源点和超级汇点,将源点与行相连,容量为这行消灭敌人的代价,将列与汇点相连,容量为这列消灭敌人的代 ...
- POJ - 3308 Paratroopers(最大流)
1.这道题学了个单词,product 还有 乘积 的意思.. 题意就是在一个 m*n的矩阵中,放入L个敌军的伞兵,而我军要在伞兵落地的瞬间将其消灭.现在我军用一种激光枪组建一个防御系统,这种枪可以安装 ...
- POJ3308 Paratroopers(最小割/二分图最小点权覆盖)
把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...
随机推荐
- What does addScalar do?
The JavaDoc says: SQLQuery org.hibernate.SQLQuery.addScalar(String columnAlias, Type type) Declare a ...
- 分布式数据存储 - MySQL双主复制
上篇文章<分布式数据存储 - MySQL主从复制>,我们说到MySQL主从复制很好的保障了从库,读的高可用性.so,问题来了: 1.针对主库,写的高可用性又是如何做到高可用性? 2.如果需 ...
- 定时每天执行前一天的数据导入oracle
#!/bin/bash export LANG="en_US.UTF-8" #设定时间变量,为前一天时间 log_date=`date +%Y-%m-%d -d "-1 ...
- c#百分比
<div class="inner" style="width:@string.Format("{0:P1}", item.Maturitys) ...
- PHP开发入行真功夫 三扬科技
前言与目录 PHP开发入行真功夫 前言 PHP开发入行真功夫 目录 第2章 基本语法 2.1.1 判断闰年程序 2.1.2 我们现在能做的…… 2.2.1 PHP的语言概貌 2.2.2 为我们的程 ...
- Good Bye 2015 B. New Year and Old Property 计数问题
B. New Year and Old Property The year 2015 is almost over. Limak is a little polar bear. He has re ...
- poj 3522(最小生成树应用)
题目链接:http://poj.org/problem?id=3522思路:题目要求最小生成树中最大边与最小边的最小差值,由于数据不是很大,我们可以枚举最小生成树的最小边,然后kruskal求最小生成 ...
- SSH 端口转发
第一部分 概述 当你在咖啡馆享受免费 WiFi 的时候,有没有想到可能有人正在窃取你的密码及隐私信息?当你发现实验室的防火墙阻止了你的网络应用端口,是不是有苦难言?来看看 SSH 的端口转发功能能给我 ...
- 连接池和 "Timeout expired"异常【转】
异常信息: MySql.Data.MySqlClient.MySqlException (0x80004005): error connecting: Timeout expired. The tim ...
- linux系统中如何进入退出vim编辑器,方法及区别
在linux家族中,vim编辑器是系统自带的文本编辑器,其功能强大自不必说了.偶有小白,刚接触linux,要修改某个文本文件,不可能像WINDOWS那样操作,更有甚者,进入VI编辑器后,无法退出以致强 ...