二分图最大匹配(匈牙利算法) POJ 3020 Antenna Placement

 

题目传送门

  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 }

 

posted @ 2015-07-16 19:29  Running_Time  阅读(192)  评论(0编辑  收藏  举报