http://poj.org/problem?id=3041
题意:在N*N的网格中有K颗小行星。小行星i的位置是(Ri,Ci)。用一个武器发射光束,可以把一行或者一列的小行星消除。要摧毁所有小行星,至少要用多少束光束。
题解:二分图匹配的模型之一。以横坐标和纵坐标做匹配。其实这是最小顶点覆盖问题,但在二分图中等于最大匹配。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 #include <cstdlib> 5 #include <cmath> 6 #include <string> 7 #include <vector> 8 #include <list> 9 #include <map> 10 #include <queue> 11 #include <stack> 12 #include <bitset> 13 #include <algorithm> 14 #include <numeric> 15 #include <functional> 16 #include <set> 17 #include <fstream> 18 19 using namespace std; 20 21 const int maxn=10010; 22 int g1[maxn]; 23 int g2[maxn]; 24 int V; 25 vector<int> G[maxn*2 ]; 26 int match[maxn]; 27 bool used[maxn]; 28 29 void add_edge(int u,int v){ 30 G[u].push_back(v); 31 G[v].push_back(u); 32 } 33 34 bool dfs(int v) 35 { 36 used[v]=true; 37 for (int i=0; i<G[v].size(); i++) { 38 int u=G[v][i]; 39 int w=match[u]; 40 if (w<0||!used[w]&&dfs(w)) { 41 match[v]=u; 42 match[u]=v; 43 return true; 44 } 45 } 46 return false; 47 } 48 49 int b_match() 50 { 51 int res=0; 52 memset(match, -1, sizeof(match)); 53 for (int v=0; v<V; v++) { 54 if (match[v]<0) { 55 memset(used, 0, sizeof(used)); 56 if (dfs(v)) { 57 res++; 58 } 59 } 60 } 61 return res; 62 } 63 int main() 64 { 65 //freopen("/Users/apple/Desktop/POJ 3041/POJ 3041/in", "r", stdin); 66 //freopen("/Users/apple/Desktop/POJ 3041/POJ 3041/out", "w", stdout); 67 int N,K; 68 scanf("%d%d",&N,&K); 69 V=N*2; 70 for (int i=0; i<K; i++) { 71 scanf("%d%d",&g1[i],&g2[i]); 72 add_edge(g1[i]-1, N+g2[i]-1); 73 } 74 printf("%d ",b_match()); 75 76 return 0; 77 }