POJ 3041.Asteroids 最小顶点覆盖

时间:2021-07-13 06:16:21
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 22905   Accepted: 12421

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

Source

题意:在一个n*n的格子中有k个物品。现在有一种炸弹可以炸掉一排或者一竖的物品,求最少需要几颗炸弹才能把物品全部炸掉。
思路:
POJ 3041.Asteroids 最小顶点覆盖
对网格的x,y建立联系,如果xi,yi有物品,那么就建立联系。选最少的顶点炸掉所有的物品,就是一个最小顶点覆盖问题,即最少的顶点覆盖图的所有的边。最小顶点覆盖是个NP问题,没有高效的算法。不过对于二分图而言,最大匹配=最小顶点覆盖
证明:首先,最小顶点覆盖不能小于最大匹配。每条匹配边链接的两个匹配点a,b中。最多有1个点链接为匹配点,否者可以去掉当前匹配边,增加2条匹配边,不符合最大匹配。现在选取每个匹配边链接的匹配点中的一个(如果有连接未匹配点就选它),目前最大匹配=最小顶点覆盖,那么有没有边没有包含进去呢?如果有的话,那么这条边的两个顶点只能是未匹配点,这样的话又与最大匹配不符,所以在二分图中,最大匹配=最小顶点覆盖。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<vector>
using namespace std;
#define PI acos(-1.0)
typedef long long ll;
typedef pair<int,int> P;
const int maxn=1e5+,maxm=1e5+,inf=0x3f3f3f3f,mod=1e9+;
const ll INF= 1e13+;
priority_queue<P,vector<P>,greater<P> >q;
vector<int>G[maxn];
int vis[maxn],cy[maxn];
int dfs(int u)
{
for(int i=; i<G[u].size(); i++)
{
int v=G[u][i];
if(vis[v]) continue;
vis[v]=true;
if(cy[v]==-||dfs(cy[v]))
{
cy[v]=u;
return true;
}
}
return false;
}
int solve(int n)
{
int ans=;
memset(cy,-,sizeof(cy));
for(int i=; i<=n; i++)
{
memset(vis,,sizeof(vis));
ans+=dfs(i);
}
return ans;
}
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=; i<=k; i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
}
cout<<solve(n)<<endl;
return ;
}

二分图最小顶点覆盖