poj3308 Paratroopers 最大流 最小点权覆盖
题意:有一个n*m的矩阵,告诉了在每一行或者每一列安装大炮的代价,每一个大炮可以瞬间消灭这一行或者这一列的所有敌人,然后告诉了敌人可能出现的L个坐标位置,问如何安置大炮,使花费最小。如果一个敌人位于第r行c列,则他可以被第r行或者第c列的大炮消灭。
链接:http://poj.org/problem?id=3308
这题突然就让我想起来那个多校的那道多米诺骨牌的那个,几乎一样的模型,还不过要把权值改一下,因为权值是相乘,那么就吧权值改成相加,也就是用log去改变。
这样的话 如果坐标为x,y的点要被消灭,那么要么走x要么走y,这样的话就直接是一个二分图的形式了。一边是行,一边是列,用出现的点连边,就是最小点权模型,最小点权模型就是集合x点的点权做为s-x的边权(流量),y点的权值为y-t的边权,x-y的边权为无穷大,这样见图那么就可以用最大流搞。
这是我曾经看过的一个大神对于二分图边权覆盖的讲解。好像就是这道题。
求二分图顶点覆盖问题,都是转化为最小割问题去求解,转化方法如下:
建超级源S 和超级汇 T,假设二分图两个点集分别为 X 和 Y。X和Y原来的边容量设为INF,将S到X里每个点x连一条边,边权为x的点权,也可以看做覆盖点x的所有出边的花费(W-),将Y里每个点y到T连一条边,边权为y的点权,也可以看做覆盖点y的所有入边的花费(W+)。这样求得最小割容量,即为原问题的解。
/************这是对这个转化方法的解释和证明,有兴趣的同学可以看看************/
X到Y的边权为INF,自然不会成为最小割中的边,那就只有可能是S到X和Y到T中的边,而:S到X中点x的边e1, 权为点x的点权,点x和Y中的所有临边e2,都需要受到e1的流量的限制,同样,X到Y中点y的所有边也会受到点y到T的容量限制。这样求得割就能保证覆盖掉所有的边。
我们可以用反证法证明一下:假设有边<x, y>没有被覆盖掉,则边<S, x>流量为0且边<y, T>流量为0,而<x, y>流量为INF,自然可以找到一条S到T的增流路径<S, x, y, T>,与以求得流为最大流相矛盾,则可以说明,在最大流的情况下,所有的边都已经被覆盖掉。
而最小割问题可以用最大流来解决,问题就变得简单了。
/****************************************************************************/
#include <stdio.h>
#include <iostream>
#include <queue>
#include <string.h>
#include <vector>
#include <cmath>
using namespace std;
const double maxn = 1000000.0;
int m,n,l;
double row[],col[];
struct edge
{
int u,v;
double cap,flow;
};
vector<edge>edges;
vector<edge>ed;
vector<int>g[],G[]; void addedge(int u,int v,double cap,double flow)
{
edges.push_back((edge){u,v,cap,flow});
edges.push_back((edge){v,u,,});
int m;
m = edges.size();
g[u].push_back(m-);
g[v].push_back(m-);
} void init(int n)
{
int i;
for(i = ;i <= n;i++)
{
g[i].clear();
}
edges.clear();
}
int vis[],dis[],cur[];
int bfs(int s,int t,int n)
{
memset(vis,,sizeof(vis));
queue<int>q;
q.push(s);
dis[s] = ;
vis[s] = ; while(!q.empty())
{
int u,v;
u = q.front();
q.pop();
for(int i = ;i < g[u].size();i++)
{
edge &e = edges[g[u][i]];
v = e.v;
if(!vis[v] && e.cap-e.flow > )
{
vis[v] = ;
dis[v] = dis[u] +;
q.push(v);
}
}
}
return vis[t];
}
double dfs(int u,double a,int t)
{
if(u == t || a == )
return a;
int v;
double flow = ,f;
for(int& i = cur[u]; i < g[u].size();i++)
{
edge &e = edges[g[u][i]];
v = e.v;
if(dis[u]+ == dis[v] &&(f = dfs(v,min(a,e.cap-e.flow),t)))
{
e.flow += f;
edges[g[u][i]^].flow -= f;
flow += f;
a -= f;
if(a == )
break;
}
} return flow;
}
double maxflow(int s,int t)
{
double flow = ;
while(bfs(s,t,t))
{
memset(cur,,sizeof(cur));
flow+=dfs(s,,t);
}
return flow;
} int main()
{
int i,j;
int t; while(~scanf("%d",&t))
{
while(t--)
{
scanf("%d %d %d",&n,&m,&l);
init(n+m+); for(i=;i <= n;i++)
scanf("%lf",&row[i]); for(i = ;i <= m;i++)
scanf("%lf",&col[i]); int u,v; for(i = ;i <= n;i++)
addedge(,i,log(row[i]),);
for(i = ;i <= m;i++)
addedge(n+i,n+m+,log(col[i]),); for(i = ;i <= l;i++)
{
int a,b;
scanf("%d %d",&a,&b);
addedge(a,n+b,maxn,);
} double ans = maxflow(,n+m+);
printf("%.4f\n",exp(ans));
}
} return ;
}
poj3308 Paratroopers 最大流 最小点权覆盖的更多相关文章
- POJ 3308 Paratroopers (对数转换+最小点权覆盖)
题意 敌人侵略r*c的地图.为了消灭敌人,可以在某一行或者某一列安置超级大炮.每一个大炮可以瞬间消灭这一行(或者列)的敌人.安装消灭第i行的大炮消费是ri.安装消灭第j行的大炮消费是ci现在有n个敌人 ...
- poj 3308 Paratroopers(二分图最小点权覆盖)
Paratroopers Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 8954 Accepted: 2702 Desc ...
- POJ3308 Paratroopers(最小割/二分图最小点权覆盖)
把入侵者看作边,每一行每一列都是点,选取某一行某一列都有费用,这样问题就是选总权最小的点集覆盖所有边,就是最小点权覆盖. 此外,题目的总花费是所有费用的乘积,这时有个技巧,就是取对数,把乘法变为加法运 ...
- poj3308 Paratroopers --- 最小点权覆盖->最小割
题目是一个非常明显的二分图带权匹配模型, 加入源点到nx建边,ny到汇点建边,(nx.ny)=inf建边.求最小割既得最小点权覆盖. 在本题中因为求的是乘积,所以先所有取log转换为加法,最后再乘方回 ...
- 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 Paratroopers(最小点权覆盖)(对数乘转加)
http://poj.org/problem?id=3308 r*c的地图 每一个大炮可以消灭一行一列的敌人 安装消灭第i行的大炮花费是ri 安装消灭第j行的大炮花费是ci 已知敌人坐标,同时消灭所有 ...
- POJ - 3308 Paratroopers (最小点权覆盖)
题意:N*M个格点,K个位置会有敌人.每行每列都有一门炮,能打掉这一行(列)上所有的敌人.每门炮都有其使用价值.总花费是所有使用炮的权值的乘积.求最小的总花费. 若每门炮的权值都是1,就是求最小点覆盖 ...
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
/** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...
- POJ 2125 Destroying the Graph 二分图最小点权覆盖
Destroying The Graph Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 8198 Accepted: 2 ...
随机推荐
- vue项目中多个入口的配置
出处:http://www.qingpingshan.com/jb/javascript/221105.html 基于vue2.0生成项目,一段时间都在找如何配置成多个页面的.网上有这样的例子相对也是 ...
- 工作笔记-javascript-网络层封装
/** * @Author Mona * @Date 2016-12-08 * @description 网络层封装 */ /** * 封装基本请求方式 */ window.BaseRequest = ...
- yii2 中where条件查询
在Yii的Model里进行查询的时候 where是必不可少的. Where方法声明为 static where( $condition ) 其中参数 $condition 类型为字符串或者数组1.字符 ...
- python中变量的交换
a=4 b=5 #第一种 c=0 c=a a=b b=c print('a=%d,b=%d'%(a,b)) #第二种 a=a+b b=a-b a=a-b print('a=%d,b=%d'%(a,b) ...
- cdoj1588 潘爷泡妹
地址:http://acm.uestc.edu.cn/#/problem/show/1588 题目:复制过来发现有问题,自己去cdoj看吧 思路: 1.先进行多次spfa跑出所有人之间的相互到达所需要 ...
- HTTPS复习
Https Https其实是两个协议,即HTTP协议和SSL协议,但是由于HTTP协议应用广泛,而且需要为其提供数据隐私保护,所以将HTTP协议与SSL协议结合.HTTP属于应用层,在远古时代,它只需 ...
- 播放48KHZ有1S的停顿
两个音频文件: /usr/lib/gstreamer-0.10/libgstflump3dec.so /usr/lib/gstreamer-0.10/libgstflumpegdemux.so
- AVAudioSession(1):iOS Audio Session 概览
本文转自:AVAudioSession(1):iOS Audio Session 概览 | www.samirchen.com 本文内容主要来源于 Audio Session Programming ...
- centos6.9 升级glibc(升级到 2.17版)
原系统centos6.9自带GLIBC_2.12,安装一些软体提示版本不对,决定升级. wget http://ftp.gnu.org/gnu/glibc/glibc-2.17.tar.gz tar ...
- Python3.x:常用基础语法
Python3.x:常用基础语法 1,if else语句: 不执行if内的语句,需要用:pass if i>2: #跳过不执行 pass else: print("i= %s" ...