Case 1: 3
刷匈牙利算法专题中的第四题。把每个'#'编号,然后和上下左右四个方向相邻的'#'的连边,之后套一下匈牙利的模板就好了,结果就是最大匹配。数据范围看着很凶残,刚开始用邻接链表撸了一发,发现实际很水,又用邻接矩阵搞了一发
//邻接表实现的匈牙利算法
#include
#include
#include
#include
#include
using namespace std;
const int N = 620;
char s[N][N];
int mpa[N][N];
int match[N*10];
bool use[N*10];
vector G[N*10];
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
int cnt;
void add_edge(int a, int b)
{
G[a].push_back(b);
G[b].push_back(a);
}
bool dfs(int v)
{
use[v] = true;
for(int i = 0; i < G[v].size(); i++)
{
int u = G[v][i], w = match[u];
if(w == -1 || (! use[w] && dfs(w)))
{
match[v] = u;
match[u] = v;
return true;
}
}
return false;
}
int hungary()
{
int res = 0;
memset(match, -1, sizeof match);
for(int i = 1; i < cnt; i++)
{
if(match[i] < 0)
{
memset(use, 0, sizeof use);
if(dfs(i)) res++;
}
}
return res;
}
int main()
{
int t, n, x = 0;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf(" %s", s[i]);
memset(mpa, 0, sizeof mpa);
cnt = 1;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(s[i][j] == '#')
mpa[i][j] = cnt++;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(mpa[i][j] != 0)
{
for(int k = 0; k < 4; k++)
{
int nx = i + dx[k], ny = j + dy[k];
if(nx >= 0 && nx < n && ny >= 0 && ny < n && mpa[nx][ny] != 0)
add_edge(mpa[i][j], mpa[nx][ny]);
}
}
}
printf("Case %d: %d\n", ++x, hungary());
for(int i = 1; i < cnt; i++)
G[i].clear();
}
return 0;
}
//邻接矩阵实现的匈牙利算法
#include
#include
#include
#include
#include
using namespace std;
const int N = 620;
char s[N][N];
int mpa[N][N];
int match[N*2];
bool use[N*2];
bool gap[N*2][N*2];
int dx[] = {0, 0, 1, -1}, dy[] = {1, -1, 0, 0};
int cnt;
bool dfs(int v)
{
for(int i = 1; i < cnt; i++)
{
if(gap[v][i] == true && use[i] == false)
{
use[i] = true;
if(match[i] == -1 || dfs(match[i]))
{
match[i] = v;
return true;
}
}
}
return false;
}
int hungary()
{
int res = 0;
memset(match, -1, sizeof match);
for(int i = 1; i < cnt; i++)
{
memset(use, 0, sizeof use);
if(dfs(i)) res++;
}
return res;
}
int main()
{
int t, n, x = 0;
scanf("%d", &t);
while(t--)
{
scanf("%d", &n);
for(int i = 0; i < n; i++)
scanf(" %s", s[i]);
memset(mpa, 0, sizeof mpa);
memset(gap, 0, sizeof gap);
cnt = 1;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
if(s[i][j] == '#')
mpa[i][j] = cnt++;
for(int i = 0; i < n; i++)
for(int j = 0; j < n; j++)
{
if(mpa[i][j] != 0)
{
for(int k = 0; k < 4; k++)
{
int nx = i + dx[k], ny = j + dy[k];
if(nx >= 0 && nx < n && ny >= 0 && ny < n && mpa[nx][ny] != 0)
gap[mpa[i][j]][mpa[nx][ny]] = true;
}
}
}
printf("Case %d: %d\n", ++x, hungary() / 2);
}
return 0;
}