题目链接:http://poj.org/problem?id=3041
Asteroids
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 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 |
这也是一道比较简单的二分匹配的题目。把光束当作图的顶点,而把小行星当作连接对应光束的边,如此一来,光束的攻击方案即对应一个顶点集合s。图中每一条边至少有一个属于s的端点。转换成了最小顶点覆盖问题。
在二分图中 最大匹配=最小顶点覆盖
于是用二分匹配可解:
#include<iostream> #include<algorithm> #include<cstdio> #include<cstring> #include<vector> #include<queue> using namespace std; const int MAX=1010; vector<int> G[MAX]; int match[MAX],r[MAX],c[MAX]; bool used[MAX]; int k,V,n; void add_edge(int u,int v) { G[u].push_back(v); G[v].push_back(u); } bool dfs(int v) { used[v]=true; for(int i=0;i<G[v].size();i++) { int u=G[v][i],w=match[u]; if(w<0||!used[w]&&dfs(w)) { match[v]=u; match[u]=v; return true; } } return false; } int bipartite_matching() { int res=0; memset(match,-1,sizeof(match)); for(int v=1;v<=V;v++) { if(match[v]<0) { memset(used,0,sizeof(used)); if(dfs(v)) { res++; } } } return res; } int main() { while(cin>>n>>k) { V=n*2; for(int i=0;i<k;i++) { int r,c; scanf("%d%d",&r,&c); add_edge(r,n+c); } cout<<bipartite_matching()<<endl; } return 0; }
poj3041(二分匹配简单题)