poj3041

受下列文章启发:

http://kukumayas.iteye.com/blog/1075610

http://blog.csdn.net/lyy289065406/article/details/6646007

把每一行每一列都当成一个节点来看待,把每个外星人的坐标当成一条边看待,

这样就可以把问题转化成求“最小点覆盖”,由于K?nig定理,再转换成求“最大二分图匹配”,

于是就可以用匈牙利算法。匈牙利算法有一个核心概念就是找增广路,如果有增广路,

则匹配加一,而找增广路的核心就是一个交差树的概念。

至于增广路和二分图以及二分图匹配,交差树的概念上面两个链接地址的文章多看看应该就能领悟了。

(个人IQ比较低,看了大概两三个小时的样子才明白)

由于用dfs来实现找增广路较bfs来说形式上更加简洁,所以这道题的求增广路是否存在采用dfs来做,

第一个链接里的模拟就是dfs找增广路的模拟。

下面是我的代码,以及一些注释,这是我第一次写匈牙利算法,所以详细地写了一些注释,供大家参考。

#include<iostream>
#include<cstring>
using namespace std;
int link[510],num_dian;//link用来存放已经连通的点,由于这里二分图的两个子图的顶点数相同,所以统一用num_dian来存放顶点数
bool map[510][510],visit[510];//map用来存放可存在的边,visit的作用是在dfs中避免搜索起始点陷入死循环,搜索中访问过的点就进行标记(我这里把每一行当作起始点,当然每一列也是可以的)
bool dfs(int x)
{
	int i;
	for(i=1;i<=num_dian;i++)
	{
		if(map[x][i]==1&&visit[i]==0)//如果x-i边可连同且i点没有被访问
		{
			visit[i]=1;//访问此点,并标记
			if(link[i]==0||dfs(link[i])==1)//如果i点未被连同,或者通过dfs实现以当前i的连通点为起点交差树搜索是否有尚未连通的点加入
			{
				link[i]=x;//连同i,x两点
				return 1;//返回1表示可以增加一个新的匹配
			}
		}
	}
	return 0;//返回0表示此时无法增加一个新的匹配
}
int xiongyali()
{
	int i,sum;
	sum=0;
	for(i=1;i<=num_dian;i++)//从一个子图的点(这里是代表每一行的点)出发,找是否还能够匹配,也就是找增广路
	{
		memset(visit,0,sizeof(visit));
		if(dfs(i))
		sum++;
	}
	return sum;
}
int main()
{
	int n,k,i,row,line,sum;
	memset(map,0,sizeof(map));
	memset(link,0,sizeof(link));
	scanf("%d%d",&n,&k);
	num_dian=n;
	for(i=0;i<k;i++)
	{
		scanf("%d%d",&row,&line);
		map[row][line]=1;
	}
	printf("%d\n",xiongyali());
}

poj3041

时间: 2024-08-29 09:12:08

poj3041的相关文章

poj3041 Asteroids --- 最小点覆盖

#include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<vector> #include<queue> const int maxn=510; using namespace std; int my[maxn],mx[maxn],vis[maxn],e[maxn][maxn],n;

poj3041(Asteroids)

题目地址:Asteroids 题目大意: 给你一个N*N 的格子,在给你星星所在的坐标位置,操作是每次可以消除一整行或一列的星星,问你最小需要多少次操作. 解题思路: 关键是需要往二分匹配上想.你可以先画图,把星星位置的坐标行和列建图,(1->1,1->3)/(2->2)/(3->2).将所有的边消去就是将所有的星星消去怎么才能最少?这里需要想到连得边最多的点,因为所有的边汇集到一点意思为可以同时消去.所以你只需找到最少的点覆盖所有的边即可,二分图里最小的点覆盖等于最大匹配数.(证

POJ3041 二分图最大匹配

问题:POJ3041 分析: 构造二分图:令A = B = { 1, 2, ... , n }, 分别代表行号集与列号集.假如第i行第j列有一颗行星,则连接Ai与Bj, 表示必须从Ai(即第i行),Bj(即第j列)中选择一个射击.最小射击数等价于覆盖所有边的最小点集S的大小.问题转化为最小顶点覆盖问题. 因为最小顶点覆盖=最大匹配数,故直接用匈牙利算法求解. AC代码 1 //Memory: 1260K Time: 47MS 2 #include <iostream> 3 using name

POJ3041 Asteroids

Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 20458   Accepted: 11098 Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K a

poj3041(二分匹配简单题)

题目链接:http://poj.org/problem?id=3041 Asteroids Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14022   Accepted: 7629 Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <

解题报告 之 POJ3041 Asteroids

解题报告 之 POJ3041 Asteroids Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at t

POJ3041 Asteroids【二分图最小点覆盖】

题目链接: http://poj.org/problem?id=3041 题目大意: 有一个N*N的矩阵,有些格子上有障碍物(坐标为(x,y) ),在消除这些障碍物的时候,可以一次性消除 该障碍物同一行所有的障碍物,或是一次性消除该障碍物同一列所有的障碍物.只能选择清理该行或是 清理该列.问:最小进行多少次消除,就可以清理所有的障碍物. 思路: 可以将每一行当做一个点,这样总共有N个点,作为二分图的一边.将每一列当做一个点,这样又有N 个点,作为二分图的另一边.将有障碍物的行点和列点连接起来,每

poj3041 建图+最小顶点覆盖(最大匹配数)

这个题的意思是给你一个N*N的矩阵, 里面有K个星球, 我们可以让武器攻击矩阵的一行或者一列来使得这个星球被击碎, 现在问你最少需要几个这种武器才能把所有的星球击碎, 首先我们可以知道每个武器最多攻击一行一次, 因此最多有2*N个武器, 另外我们可以将武器看成顶点, 星球看成边,连接一副图,求出这个图的最小顶点覆盖数也就是最大匹配数即可, 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #i

poj3041 Asteroids(二分图最小顶点覆盖、二分图匹配)

Description Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 <= N <= 500). The grid contains K asteroids (1 <= K <= 10,000), which are conveniently located at the lattice points of the