您的位置:首页 > 其它

poj 3041 Asteroids 二分图最小点覆盖

2014-03-31 20:27 357 查看
Asteroids

Time Limit: 1000MS Memory Limit: 65536K

Total Submissions: 13764 Accepted: 7485

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

======================================================================================

题目大意:有一片正方形区域,里面有若干颗陨石(或者小行星吧,意会,意会)挡路,我们的星舰有一种超级武器,发射一次能抹消掉某一行或某一列所有的障碍物。但是发射一次消耗巨大,问最少来几发能把前面这些障碍物清理干净。

解题思路:正方形中的每一个坐标把一行与一列联系起来,行跟行没关系,列跟列没关系,如果把所有行看做一个点集,所有列看做另一个点集,则可以得到一个二分图。问题也变成了至少需要多少个点能覆盖二分图中的所有边。可以使用二分图最大匹配求最小点覆盖的公式,也就是两者相等。

在此向csdn的名ACMer小优致敬并给跪,相信去翻了她QQ空间后大家也会回来跟我一起跪的orz。

//Memory: 612K Time: 0MS

#include<cstdio>
#include<cstring>
#include<vector>
using namespace std;

const int MAXN = 501; //题中给的坐标都是从1开始的所以最大500+1
int N , K , linker[MAXN]; //邻接表也多建一个vector,这样等下比较方便
bool used[MAXN];
vector<int> g[MAXN]; //建立邻接表
//匈牙利算法
bool dfs(int v)
{
for( int i = 0 ; i < g[v].size() ; i++ )
{
int u = g[v][i];
if( !used[u] )
{
used[u] = true;
if( !linker[u] || dfs(linker[u]) )
{
linker[u] = v;
return true;
}
}
}
return false;
}

int hungary()
{
int res = 0;
memset(linker,0,sizeof(linker));
for( int i = 1 ; i <= N ; i++ )
{
memset(used,false,sizeof(used));
if( dfs(i) )
res++;
}
return res;
}

int main()
{
while( ~scanf("%d%d", &N , &K) ) //题目没说有多组测试用例但是我可是被各大oj坑怕了
{
for( int i = 1 ; i <= N ; i++ ) //初始化邻接表
g[i].clear();
for( int i = 0 ; i < K ; i++ )
{
int r , c;
scanf("%d%d" , &r, &c);
g[r].push_back(c); //接进来就可以直接建立边了
}
printf("%d\n", hungary()); //直接使用匈牙利算法
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息