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

若每门炮的权值都是1,就是求最小点覆盖的问题,参考:http://poj.org/problem?id=3041

将行视作X部,列视作Y部,敌人(i,j)视作连接点i和点N+j的边,要求一个点集合,使其能覆盖所有的边,且权值之积最小,即求最小点权覆盖.与求最大权独立集一样,也是用网络流求解.

这里处理积的方法是,将权值取对数,则log(a*b) = log(a) + log(b),转化为了加法运算.

建图步骤:建立源点s与汇点t.从源点s向X部的点建边,从Y部的点向汇点t建边,容量为其权值取对数.对敌人(i,j),由i向j+N建容量为正无穷的边.

跑出最大流即为其最小点权覆盖的值,最后pow计算出实际花费.

*其实带权的二分图,用网络流求最小点权覆盖与求最大独立集还是运用了二分图中的思想.二分图中,|最大独立集| = N - |最小点权覆盖| = N - |最大匹配|.

而在用网络流求解时,|最大流| = |最小割| = |最小点权覆盖|, |最大权独立集| = |总权值| - |最小点权覆盖| = |总权置| - |最大流|

#include<iostream>
#include<cstring>
#include<stdio.h>
#include<algorithm>
#include<string>
#include<cmath>
using namespace std;
const double INF = 100000.0;
const int MAXN=3010;//点数的最大值
const int MAXM=400010;//边数的最大值
#define captype double struct SAP_MaxFlow{
struct Edge{
int from,to,next;
captype cap;
}edges[MAXM];
int tot,head[MAXN];
int gap[MAXN];
int dis[MAXN];
int cur[MAXN];
int pre[MAXN]; void init(){
tot=0;
memset(head,-1,sizeof(head));
}
void AddEdge(int u,int v,captype c,captype rc=0){
edges[tot] = (Edge){u,v,head[u],c}; head[u]=tot++;
edges[tot] = (Edge){v,u,head[v],rc}; head[v]=tot++;
}
captype maxFlow_sap(int sNode,int eNode, int n){//n是包括源点和汇点的总点个数,这个一定要注意
memset(gap,0,sizeof(gap));
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
pre[sNode] = -1;
gap[0]=n;
captype ans=0;
int u=sNode;
while(dis[sNode]<n){
if(u==eNode){
captype Min=INF ;
int inser;
for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to])
if(Min>edges[i].cap){
Min=edges[i].cap;
inser=i;
}
for(int i=pre[u]; i!=-1; i=pre[edges[i^1].to]){
edges[i].cap-=Min;
edges[i^1].cap+=Min;
}
ans+=Min;
u=edges[inser^1].to;
continue;
}
bool flag = false;
int v;
for(int i=cur[u]; i!=-1; i=edges[i].next){
v=edges[i].to;
if(edges[i].cap>0 && dis[u]==dis[v]+1){
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag){
u=v;
continue;
}
int Mind= n;
for(int i=head[u]; i!=-1; i=edges[i].next)
if(edges[i].cap>0 && Mind>dis[edges[i].to]){
Mind=dis[edges[i].to];
cur[u]=i;
}
gap[dis[u]]--;
if(gap[dis[u]]==0) return ans;
dis[u]=Mind+1;
gap[dis[u]]++;
if(u!=sNode) u=edges[pre[u]^1].to; //退一条边
}
return ans;
}
}F; int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
int T; scanf("%d", &T);
double cap;
int u,v,tmp;
while(T--){
F.init();
int n,m,k; scanf("%d %d %d",&n, &m,&k);
int s = 0, t = n+m+1;
for(int i=1;i<=n;++i){
scanf("%lf", &cap);
F.AddEdge(s,i,log(cap));
}
for(int i=1;i<=m;++i){
scanf("%lf", &cap);
F.AddEdge(i+n,t,log(cap));
}
while(k--){
scanf("%d %d",&u,&v);
F.AddEdge(u,v+n,INF);
}
double res = exp(F.maxFlow_sap(s,t,t+1));
printf("%.4lf\n",res);
}
return 0;
}

POJ - 3308 Paratroopers (最小点权覆盖)的更多相关文章

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

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

  2. POJ 3308 Paratroopers(最小割EK(邻接表&矩阵))

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

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

    意甲冠军: 一m*n该网络的规模格.详细地点称为伞兵着陆(行和列). 现在,在一排(或列) 安装激光枪,激光枪可以杀死线(或塔)所有伞兵.在第一i安装一排 费用是Ri.在第i列安装的费用是Ci. 要安 ...

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

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

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

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

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

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

  7. POJ 3308 Paratroopers (对数转换+最小点权覆盖)

    题意 敌人侵略r*c的地图.为了消灭敌人,可以在某一行或者某一列安置超级大炮.每一个大炮可以瞬间消灭这一行(或者列)的敌人.安装消灭第i行的大炮消费是ri.安装消灭第j行的大炮消费是ci现在有n个敌人 ...

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

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

  9. poj 2125 Destroying The Graph (最小点权覆盖)

    Destroying The Graph http://poj.org/problem?id=2125 Time Limit: 2000MS   Memory Limit: 65536K       ...

随机推荐

  1. RabbitMQ组成及原理介绍-3

    rabbitmq作为成熟的企业消息中间件,实现了应用程序间接口调用的解耦,提高系统的吞吐量. 1.RabbitMQ组成 是由 LShift 提供的一个 Advanced Message Queuing ...

  2. ChemDraw中化学信息怎么通过Excel搜索

    用户可以通过ChemDraw for Excel插件功能在Office Excel中建立ChemOffice菜单将ChemOffice和Excel结合使用,使用电子表格的最大优势之一就是可以清晰查看并 ...

  3. WPS长文档编辑技巧之二:对样式的设置与修改

    目录:       1.使用系统内置样式 2.如何修改样式 3.如何自定义样式 4.在文档使用多级编号 5.结合样式编辑文档大纲 6.利用文档结构图查看大纲结构 正文: 1.使用系统内置样式 在使用样 ...

  4. oracle怎么把一个用户下的表复制给另一个用户?(授予表权限)

    //把system读写权限 授权给scottselect 'Grant all on '||table_name||' to scott;' from all_tables where owner = ...

  5. html 事件处理程序中的代码在执行时,有权访问全局作用域中的任何代码。

    看一个简单的例子: html: <head> <meta charset="UTF-8"> <title>Document</title& ...

  6. coderfun-boot接私活利器,文档详实,非一般的开发速度

    项目主页:https://gitee.com/klguang/coderfun-boot 演示地址:http://106.15.195.9:8080/admin/项目文档:https://www.ka ...

  7. [ Office 365 开发系列 ] Graph Service

    前言 本文完全原创,转载请说明出处,希望对大家有用. 通过[ Office 365 开发系列 ] 开发模式分析和[ Office 365 开发系列 ] 身份认证两篇内容的了解,我们可以开始使用Offi ...

  8. PAT 甲级 1104 sum of Number Segments

    1104. Sum of Number Segments (20) 时间限制 200 ms 内存限制 65536 kB 代码长度限制 16000 B 判题程序 Standard 作者 CAO, Pen ...

  9. Spoken English Practice(Don't get me wrong, that explanation makes no difference, I'm still mad at you. Come on, be reasonable!)

    绿色:连读:                  红色:略读:               蓝色:浊化:               橙色:弱读     下划线_为浊化 口语蜕变(2017/7/11) ...

  10. Spark源码分析 – SparkContext

    Spark源码分析之-scheduler模块 这位写的非常好, 让我对Spark的源码分析, 变的轻松了许多 这里自己再梳理一遍 先看一个简单的spark操作, val sc = new SparkC ...