POJ - 3041 Asteroids(最小点覆盖数)
1、有一个n*n的矩阵,在矩阵上有k个行星,用武器射击一次可以消灭一行或者一列的行星,求消灭所有的行星的最少射击次数。
2、最小点覆盖数 = 最大匹配数
主要在于转化:看图:
这样,在建成的二分图中,一条边代表一个行星,左边的一个点代表横向射击,右边的一个点代表竖向射击。
要求最少的射击次数把所有的行星消灭,即选择最少的点,把所有的边覆盖。这不正是求最小点覆盖数吗。
ps:
顶点覆盖:在顶点集合中,选取一部分顶点,这些顶点能够把所有的边都覆盖了。这些点就是顶点覆盖集
最小顶点覆盖:在所有的顶点覆盖集中,顶点数最小的那个叫最小顶点集合。
3、
3.1匈牙利算法(邻接矩阵):
/*
顶点编号从0开始的
邻接矩阵(匈牙利算法)
二分图匹配(匈牙利算法的DFS实现)(邻接矩阵形式)
初始化:g[][]两边顶点的划分情况
建立g[i][j]表示i->j的有向边就可以了,是左边向右边的匹配
g没有边相连则初始化为0
uN是匹配左边的顶点数,vN是匹配右边的顶点数
左边是X集,右边是Y集
调用:res=hungary();输出最大匹配数
优点:适用于稠密图,DFS找增广路,实现简洁易于理解
时间复杂度:O(VE)
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; const int MAXN=;
int uN,vN;//u,v 的数目,使用前面必须赋值
int g[MAXN][MAXN];//邻接矩阵,记得初始化
int linker[MAXN];//linker[v]=u,表示v(右边Y集合中的点)连接到u(左边X集合中的点)
bool used[MAXN];
bool dfs(int u){//判断以X集合中的节点u为起点的增广路径是否存在
for(int v=;v<vN;v++)//枚举右边Y集合中的点
if(g[u][v]&&!used[v]){//搜索Y集合中所有与u相连的未访问点v
used[v]=true;//访问节点v
if(linker[v]==-||dfs(linker[v])){//是否存在增广路径
//若v是未盖点(linker[v]==-1表示没有与v相连的点,即v是未盖点),找到增广路径
//或者存在从与v相连的匹配点linker[v]出发的增广路径
linker[v]=u;//设定(u,v)为匹配边,v连接到u
return true;//返回找到增广路径
}
}
return false;
}
int hungary(){//返回最大匹配数(即最多的匹配边的条数)
int res=;//最大匹配数
memset(linker,-,sizeof(linker));//匹配边集初始化为空
for(int u=;u<uN;u++){//找X集合中的点的增广路
memset(used,false,sizeof(used));//设Y集合中的所有节点的未访问标志
if(dfs(u))res++;//找到增广路,匹配数(即匹配边的条数)+1
}
return res;
} int main(){
int i,ans;
int N,K;
int R,C;
while(~scanf("%d%d",&N,&K)){
uN=N;//匹配左边的顶点数
vN=N;//匹配右边的顶点数
memset(g,,sizeof(g));//二分图的邻接矩阵初始化
for(i=;i<K;++i){
scanf("%d%d",&R,&C);
g[--R][--C]=;//顶点编号从0开始的
}
ans=hungary();
printf("%d\n",ans);
}
return ;
}
ps:补一个用网络流解的,如下:
3.2、用网络流也可以来做,边的容量设为1即可。
用网络流的第1个模板写的,1、SAP邻接矩阵形式:
/*
SAP算法(矩阵形式)
结点编号从0开始
*/
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std; const int MAXN=;
int maze[MAXN][MAXN];
int gap[MAXN],dis[MAXN],pre[MAXN],cur[MAXN];
int sap(int start,int end,int nodenum){
memset(cur,,sizeof(cur));
memset(dis,,sizeof(dis));
memset(gap,,sizeof(gap));
int u=pre[start]=start,maxflow=,aug=-;
gap[]=nodenum;
while(dis[start]<nodenum){
loop:
for(int v=cur[u];v<nodenum;v++)
if(maze[u][v]&&dis[u]==dis[v]+){
if(aug==-||aug>maze[u][v])aug=maze[u][v];
pre[v]=u;
u=cur[u]=v;
if(v==end){
maxflow+=aug;
for(u=pre[u];v!=start;v=u,u=pre[u]){
maze[u][v]-=aug;
maze[v][u]+=aug;
}
aug=-;
}
goto loop;
}
int mindis=nodenum-;
for(int v=;v<nodenum;v++)
if(maze[u][v]&&mindis>dis[v]){
cur[u]=v;
mindis=dis[v];
}
if((--gap[dis[u]])==)break;
gap[dis[u]=mindis+]++;
u=pre[u];
}
return maxflow;
} int main(){
int i;
int N,K;
int R,C;
int S,T;//超级源点,超级汇点 while(~scanf("%d%d",&N,&K)){
memset(maze,,sizeof(maze));
for(i=;i<K;++i){
scanf("%d%d",&R,&C);
maze[R-][N+C-]=;//顶点编号从0开始的
}
//建立超级源点
S=N+N;
for(int i=;i<N;++i){
maze[S][i]=;
}
//建立超级汇点
T=N+N+;
for(int i=;i<N;++i){
maze[N+i][T]=;
} printf("%d\n",sap(S,T,N+N+)); }
return ;
}
POJ - 3041 Asteroids(最小点覆盖数)的更多相关文章
- poj 3041 Asteroids(最小点覆盖)
http://poj.org/problem?id=3041 Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions ...
- POJ 3041.Asteroids 最小顶点覆盖
Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22905 Accepted: 12421 Descr ...
- POJ 3041 Asteroids 最小覆盖数
http://poj.org/problem?id=3041 题目大意: 一辆宇宙飞船在一个小行星带中,你知道,这很危险.他有一种武器,可以清除掉一行或一列的小行星.问把小行星全部清除最少的武器使用次 ...
- poj 3041 Asteroids 最小点覆盖/最大匹配
Asteroids Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 16242 Accepted: 8833 Descriptio ...
- POJ 3041 Asteroids (最小点覆盖集)
题意 给出一个N*N的矩阵,有些格子上有障碍,要求每次消除一行或者一列的障碍,最少消除多少次可以全部清除障碍. 思路 把关键点取出来:一个障碍至少需要被它的行或者列中的一个消除. 也许是最近在做二分图 ...
- POJ 3041 Asteroids 最小点覆盖 == 二分图的最大匹配
Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape o ...
- [poj] 3041 Asteroids || 最小点覆盖=最大二分图匹配
原题 本题为最小点覆盖,而最小点覆盖=最大二分图匹配 //最小点覆盖:用最少的点(左右两边集合的点)让每条边都至少和其中一个点关联. #include<cstdio> #include&l ...
- POJ 3041 Asteroids / UESTC 253 Asteroids(二分图最大匹配,最小点匹配)
POJ 3041 Asteroids / UESTC 253 Asteroids(二分图最大匹配,最小点匹配) Description Bessie wants to navigate her spa ...
- 二分图最大匹配(匈牙利算法) POJ 3041 Asteroids
题目传送门 /* 题意:每次能消灭一行或一列的障碍物,要求最少的次数. 匈牙利算法:把行和列看做两个集合,当有障碍物连接时连一条边,问题转换为最小点覆盖数==二分图最大匹配数 趣味入门:http:// ...
- POJ 3041 Asteroids (对偶性,二分图匹配)
题目:POJ 3041 Asteroids http://poj.org/problem?id=3041 分析: 把位置下标看出一条边,这显然是一个二分图最小顶点覆盖的问题,Hungary就好. 挑战 ...
随机推荐
- XV6文件系统
文件系统 文件系统的目的是组织和存储数据,典型的文件系统支持用户和程序间的数据共享,并提供数据持久化的支持(即重启之后数据仍然可用). xv6 的文件系统中使用了类似 Unix 的文件,文件描述符,目 ...
- 【HTML/XML 6】XML文档的基本组成
导读:大致上,一个XML文档可以由三个部分组成,即声明区.定义区和文档主体区.在XML文档中,各个组成部分都包含特定的内容,有着不同的作用.本篇博客,通过分析上篇博客中的XML实例,来了解XML文档 ...
- HDU4135容斥原理
#include <cstdio> #include <string.h> #include <cmath> using namespace std; #defin ...
- 【字符串+BFS】Problem 7. James Bond
https://www.bnuoj.com/v3/external/gym/101241.pdf [题意] 给定n个字符串,大小写敏感 定义一个操作:选择任意m个串首尾相连组成一个新串 问是否存在一个 ...
- bzoj3875 【Ahoi2014】骑士游戏 spfa处理后效性动规
骑士游戏 [故事背景] 长期的宅男生活中,JYY又挖掘出了一款RPG游戏.在这个游戏中JYY会 扮演一个英勇的骑士,用他手中的长剑去杀死入侵村庄的怪兽. [问题描述] 在这个游戏中,JYY一共有两种攻 ...
- Genymotion 常见问题Unable to configure the network adapter for the virtual device解决
Genymotion 常见问题Unable to configure the network adapter for the virtual device解决 参考:http://www.pczhis ...
- Couriers(bzoj 3524)
Description 给一个长度为n的序列a.1≤a[i]≤n.m组询问,每次询问一个区间[l,r],是否存在一个数在[l,r]中出现的次数大于(r-l+1)/2.如果存在,输出这个数,否则输出0. ...
- [转]android 如何获取第三方app的sha1值
对于android 应用的sha1值和md5值的获取,如果是我们自己的应用,不论是获取测试的和正式的都是比较方便的.但是如何去获取别人开发的app的sha1和md5呢,并且我们只有apk有没有相关的文 ...
- 【收藏】实战Nginx与PHP(FastCGI)的安装、配置与优化
拜读南非蚂蚁大牛的文章真是有所收获 http://ixdba.blog.51cto.com/2895551/806622 一.什么是 FastCGI FastCGI是一个可伸缩地.高速地在HTTP s ...
- 使用windows操作EXCEL如何关闭EXCEL进程
经常项目上有导入excel的需求,其实导入一个固定格式的excel数据非常容易,但是,发现一个问题就是,导入excel后,用户在打开excel时,必须要打开2次才能打开excel,这让人很不爽:开始查 ...