二分图最大匹配(匈牙利算法) 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 }

 

你可能感兴趣的:(ant)