POJ3041轰炸行星(匈牙利算法 最小覆盖点集)

Asteroids
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 25232   Accepted: 13625

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 grid. 

Fortunately, Bessie has a powerful weapon that can vaporize all the asteroids in any given row or column of the grid with a single shot.This weapon is quite expensive, so she wishes to use it sparingly.Given the location of all the asteroids in the field, find the minimum number of shots Bessie needs to fire to eliminate all of the asteroids.

Input

* Line 1: Two integers N and K, separated by a single space. 
* Lines 2..K+1: Each line contains two space-separated integers R and C (1 <= R, C <= N) denoting the row and column coordinates of an asteroid, respectively.

Output

* Line 1: The integer representing the minimum number of times Bessie must shoot.

Sample Input

3 4
1 1
1 3
2 2
3 2

Sample Output

2

Hint

INPUT DETAILS: 
The following diagram represents the data, where "X" is an asteroid and "." is empty space: 
X.X 
.X. 
.X.
 

OUTPUT DETAILS: 

Bessie may fire across row 1 to destroy the asteroids at (1,1) and (1,3), and then she may fire down column 2 to destroy the asteroids at (2,2) and (3,2).

题目传送门:点击打开链接

题目大意:给你一个n*n的矩阵,和m个行星的坐标,你有一种武器,每一次使用可以把一行或者一列的行星清空,现在要你使用最少的次数,将行星清空,输出最少次数。

思路:因为这道题的分类是匈牙利算法,最大匹配数,所以我知道不是贪心,(其实想一下,贪心是错的)。但是头秃没思路啊,后来知道了匈牙利算法的一个重要结论,最小覆盖点集=最大匹配数,什么是最小覆盖点集呢?就是能把一副二分图所有的边都有一端点存在于这个集合中(就是把每条边都碰到了),这个点可以出现在二分图的任意一边,数量等于最大匹配数,这个结论我是现学现卖的所以大家可以自己百度证明。(与此相像的还有一个定理,是最小覆盖边集=顶点数-最大匹配数。)

利用这个结论,我们可以想,我们是要选择行和列,把所有的行星都炸掉,和这个结论中利用点,覆盖所有的边思路是一样的,所以这道题的二分图点集就是,左边是行,右边是列,然后用坐标来表示连接关系,比如存在(2,3)这个点,那就是第二行和第三列建边。最后匈牙利算法求一下就可以了。

这里再推荐一个匈牙利算法讲的很好的博客:点击打开链接

最后上代码,都不需要注释啦嘿嘿。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<queue>
#include<iostream>
#include<algorithm>
#define MAXN 10100
#define INF 0x7fffffff
#define max(a,b) a>b?a:b
#define min(a,b) a>b?b:a
using namespace std;
const int maxn=600;
int g[maxn][maxn];
int girl[maxn],used[maxn];
int n,m;
bool find(int x){
	for(int i=1;i<=n;i++){
		if(g[x][i]&&used[i]==0){
			used[i]=1;
			if(girl[i]==0||find(girl[i])){
				girl[i]=x;
				return true;
			}
		}
	}
	return false;
}
int main(){
	cin>>n>>m;
	while(m--){
		int c,r;
		scanf("%d%d",&c,&r);
		g[c][r]=1;
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		memset(used,0,sizeof(used));
		if(find(i))ans++;
	}
	printf("%d\n",ans);
}

猜你喜欢

转载自blog.csdn.net/ysk850874665/article/details/80197096
今日推荐