题意:一个地图由’.’和’#’组成,问有多少个不重叠的’##’。
思路:先将所有的’#’hash,然后建二分图,用匈牙利算法算最大匹配日数,因为边建了两次,所以结果除以二。
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
using namespace std;
struct node{
int to, next;
}edge[720100];
char mp[610][610];
int a[610][610];
int n, cnt, head[360100];
int num;
int match[360100];
bool used[360100];
void add(int u, int v)
{
edge[cnt].to = v;
edge[cnt].next = head[u];
head[u] = cnt++;
}
bool Dfs(int x)
{
for (int i = head[x]; i; i = edge[i].next)
{
int v = edge[i].to;
if (!used[v])
{
used[v] = true;
if (!match[v] || Dfs(match[v]))
{
match[v] = x;
return true;
}
}
}
return false;
}
int Matching()
{
int ans = 0;
memset(match,0,sizeof(match));
for (int i = 1; i <= num; i++)
{
memset(used, false, sizeof(used));
if (Dfs(i))
{
ans++;
}
}
return ans;
}
int main(void)
{
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
int T, cas = 1;
scanf("%d", &T);
while (T--)
{
memset(head, 0, sizeof(head));
memset(a,0,sizeof(a));
memset(mp, 0, sizeof(mp));
cnt = 1;
num = 1;
scanf("%d", &n);
for (int i = 0; i < n; i++)
scanf(" %s", mp[i]);
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
if (mp[i][j]=='#')
a[i][j] = num++;
num--;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; j++)
{
if (a[i][j])
{
if (i-1>=0 && a[i-1][j])
{
add(a[i][j], a[i-1][j]);
}
if (i+1<n && a[i+1][j])
{
add(a[i][j], a[i+1][j]);
}
if (j+1<n && a[i][j+1])
{
add(a[i][j], a[i][j+1]);
}
if (j-1>=0 && a[i][j-1])
{
add(a[i][j], a[i][j-1]);
}
}
}
}
int ans = Matching();
printf("Case %d: %d\n", cas++, ans/2);
}
return 0;
}