Asteroids POJ - 3041 二分图最小点覆盖

 
 Asteroids POJ - 3041
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).

OJ-ID:
poj-3041

author:
Caution_X

date of submission:
20191002

tags:
二分图最小点覆盖

description modelling:
给定一个N×N的网格,网格上有很多的点,现在可以一次性消除某行或者某列上的所有点,问最少需要几次可以把所有的点都消除

major steps to solve it:
思路:
(1) 建立一个二分图,两边的点分别是横坐标和纵坐标,网格上出现的点(x,y)表示二分图左边的x可以和右边的y匹配
(2) 当我们选择左边图的一个点x清除时,实际上就是把横坐标为x的点清除,那么与该点x匹配的右边图的所有点也会被一起清除,(选择右边点y清除同理)
(3) 现在问题转换成了想要覆盖所有边的最少点数,即:二分图的最小匹配点数
步骤:
(1) 建图
(2) 二分图的最小匹配=二分图的最大覆盖
二分图最大覆盖求法:
(1) 选择左图的一个点x1,遍历与该点有关的边,在右图找到一个匹配点y1,连接2点(x1,y1)
(2) 继续选择左图的点x2,如果该点对应的匹配点是y1,则查找x1有没有新的匹配点y2,若有,则(x1,y2),(x2,y1),若没有,继续找x2的匹配点,如果遍历到最后都没有找到匹配点,则继续左图的下一个点,直到左图无点可用

AC code:

#include<cstdio>
#include<cstring>
using namespace std;
int line[550][550];
int used[550],g[550];
int N,K;
bool found(int x)
{
    for(int i=1;i<=N;i++) {
        if(line[x][i]&&!used[i]) {
            used[i]=1;
            if(g[i]==-1||found(g[i])) {
                g[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    //freopen("input.txt","r",stdin);
    memset(line,0,sizeof(line));
    memset(g,-1,sizeof(g));
    scanf("%d%d",&N,&K);
    for(int i=0;i<K;i++) {
        int x,y;
        scanf("%d%d",&x,&y);
        line[x][y]=1;
    }
    int sum=0;
    for(int i=1;i<=N;i++) {
        memset(used,0,sizeof(used));
        if(found(i))    sum++;
    }
    printf("%d\n",sum);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/cautx/p/11617270.html