Poj 3041 Asteroids

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 }
原文地址:https://www.cnblogs.com/der-z/p/3690087.html