题目大意:
给定
n,m(1<=n,m<=200)
和一个
n∗m
的矩阵。矩阵由
0
和
分析:
因为最大点独立集和最小点覆盖是互补的,我们可以按最小点覆盖的操作反着来,具体参考
matrix67
的博客:http://www.matrix67.com/blog/archives/116。
AC code:
#include <cstdio>
#include <cstring>
#define ONLINE_JUDGE
using namespace std;
const int MAXN = 209;
int n, m;
int g[MAXN][MAXN];
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,1,-1};
int vis[MAXN][MAXN], cur;
int lx[MAXN][MAXN], ly[MAXN][MAXN];
int ans;
#define inside(x, y) ((x) >= 1 && (x) <= n && (y) >= 1 && (y) <= m)
int dfs(int x, int y)
{
int tx, ty;
for(int i = 0; i < 4; ++i)
{
tx = x+dx[i], ty = y+dy[i];
if(inside(tx, ty) && vis[tx][ty] != cur && g[tx][ty])
{
vis[tx][ty] = cur;
if(!lx[tx][ty] || dfs(lx[tx][ty], ly[tx][ty]))
{
lx[tx][ty] = x, ly[tx][ty] = y;
lx[x][y] = tx, ly[x][y] = ty;
return 1;
}
}
}
return 0;
}
void dfs2(int x, int y)
{
int tx, ty;
vis[x][y] = 1, g[x][y] = 2;
for(int i = 0; i < 4; ++i)
{
tx = x+dx[i], ty = y+dy[i];
if(inside(tx, ty) && !vis[tx][ty] && g[tx][ty])
{
vis[tx][ty] = 1;
if(lx[tx][ty] && !vis[lx[tx][ty]][ly[tx][ty]])
dfs2(lx[tx][ty], ly[tx][ty]);
}
}
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("sgu234.in", "r", stdin);
freopen("sgu234.out", "w", stdout);
#endif
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
{
scanf("%d", &g[i][j]);
ans += g[i][j];
}
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(!((i+j)&1) && g[i][j])
cur++, ans -= dfs(i, j);
printf("%d\n", ans);
memset(vis, 0, sizeof(vis));
for(int i = 1; i <= n; ++i)
for(int j = 1; j <= m; ++j)
if(g[i][j] && !lx[i][j] && !vis[i][j])
dfs2(i, j);
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)
if(!g[i][j]) putchar('#');
else if(g[i][j] == 2 || (!((i+j)&1) && !vis[i][j])) putchar('G');
else putchar('.');
putchar('\n');
}
#ifndef ONLINE_JUDGE
fclose(stdin);
fclose(stdout);
#endif
return 0;
}