标签:
1 /*
2 题意:*的点占据后能顺带占据四个方向的一个*,问最少要占据多少个
3 匈牙利算法:按坐标奇偶性把*分为两个集合,那么除了匹配的其中一方是顺带占据外,其他都要占据
4 */
5 #include <cstdio>
6 #include <algorithm>
7 #include <cstring>
8 #include <vector>
9 using namespace std;
10
11 const int MAXN = 4e2 + 10;
12 const int INF = 0x3f3f3f3f;
13 char s[44][11];
14 int ha[44][11];
15 bool vis[MAXN];
16 int lk[MAXN];
17 vector<int> G[MAXN];
18 int dx[4] = {-1, 1, 0, 0};
19 int dy[4] = {0, 0, -1, 1};
20 int un, vn;
21
22 bool DFS(int u)
23 {
24 for (int i=0; i<G[u].size (); ++i)
25 {
26 int v = G[u][i];
27 if (!vis[v])
28 {
29 vis[v] = true;
30 if (lk[v] == -1 || DFS (lk[v]))
31 {
32 lk[v] = u; return true;
33 }
34 }
35 }
36
37 return false;
38 }
39
40 int hungary(void)
41 {
42 int res = 0; memset (lk, -1, sizeof (lk));
43 for (int i=1; i<=un; ++i)
44 {
45 memset (vis, false, sizeof (vis));
46 if (DFS (i)) res++;
47 }
48
49 return res;
50 }
51
52 int main(void) //POJ 3020 Antenna Placement
53 {
54 //freopen ("POJ_3020.in", "r", stdin);
55
56 int t; scanf ("%d", &t);
57 while (t--)
58 {
59 int h, w; scanf ("%d%d", &h, &w);
60 for (int i=1; i<=h; ++i)
61 {
62 scanf ("%s", s[i] + 1);
63 }
64
65 un = vn = 0;
66 for (int i=1; i<=h; ++i)
67 {
68 for (int j=1; j<=w; ++j)
69 {
70 if (s[i][j] == ‘*‘)
71 {
72 if ((i+j) & 1) ha[i][j] = ++un;
73 else ha[i][j] = ++vn;
74 }
75 }
76 }
77
78 for (int i=1; i<=un; ++i) G[i].clear ();
79
80 for (int i=1; i<=h; ++i)
81 {
82 for (int j=1; j<=w; ++j)
83 {
84 if (s[i][j] == ‘*‘ && (i+j) & 1)
85 {
86 for (int k=0; k<4; ++k)
87 {
88 int tx = i + dx[k]; int ty = j + dy[k];
89 if (tx >= 1 && tx <= h && ty >= 1 && ty <= w && s[tx][ty] == ‘*‘)
90 G[ha[i][j]].push_back (ha[tx][ty]);
91 }
92 }
93 }
94 }
95
96 printf ("%d\n", un + vn - hungary ());
97 }
98
99 return 0;
100 }
二分图匹配(匈牙利算法) POJ 3020 Antenna Placement
标签:
原文地址:http://www.cnblogs.com/Running-Time/p/4652282.html