poj 3041 Asteroids 二分图最小点覆盖

来源:互联网 发布:sqoop添加数据库驱动包 编辑:程序博客网 时间:2024/05/28 20:19
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: 612KTime: 0MS#include<cstdio>#include<cstring>#include<vector>using namespace std;const int MAXN = 501;                         //题中给的坐标都是从1开始的所以最大500+1int 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;}

0 0
原创粉丝点击