UVALive 7958|Gym 101201G|Maximum Islands|二分图|最大独立点集

37 篇文章 0 订阅
31 篇文章 0 订阅

Description

You are mapping a faraway planet using a satellite.
Your satellite has captured an image of the planet’s surface. The photographed section can be modeled as a grid. Each grid cell is either land, water, or covered by clouds. Clouds mean that the surface could either be land or water, but we can’t tell.
An island is a set of connected land cells. Two cells are considered connected if they share an edge.
Given the image, determine the maximum number of islands that is consistent with the given information.

Translation

你通过卫星获得了遥远星球的照片。照片通过 nm 的二维网格表示。每个格子可以是云、水或者是陆地。云表示不知道下面是水还是陆地。
一个岛屿由一片连通的陆地格子表示。两个格子连通即两个格子相邻。
请你计算地图里最多能有多少个岛屿。

Input

The first line of input contains two space-separated integers n and m (1 ≤ n, m ≤ 40).
Each of the next n lines contains m characters, describing the satellite image. Land cells are
denoted by ‘L’, water cells are denoted by ‘W’, and cells covered by clouds are denoted by ‘C’.

Output

Print, on a single line, a single integer indicating the maximum number of islands that is consistent

样例输入

5 4
LLWL
CCCC
CCCC
CCCC
LWLL

样例输出

8

题解

一个很显然的结论:扩展已有的L是不好的(没有意义,将这些扩展的L改为W不影响答案)。所以我们可以将已有的L的四周的C直接设为W。然后剩下的C,显然一个岛一个格子的陆地就足够了(因为扩展没有意义)。
也就是说,问题已经变成对于已有的一些点,挑出最多的点使得这些点互不相邻(有边连接)。这个是最大独立点集,是NP问题,但是如果是二分图就好做了。我们可以想到,因为这个图比较规整,是格子图,因此我们黑白染色后就是二分图了(人话就是(x+y)%2的值相同的点间颜色一样,不可能相连).
也就是说,我们可以将所有的点划分为两个集合,这两组点间有边。联系到二分图的最大独立点集,即为顶点数减去最大匹配的解,因此采用匈牙利算法解决。

#include <cstdio>
#include <cstring>
#define FOR(i,j,k) for(i=j;i<=k;++i)
const int dx[] = {1, -1, 0, 0};
const int dy[] = {0, 0, 1, -1};
const int N = 2048, M = N * 8;
char mp[64][64];
bool vi[64][64];
int h[N], p[M], v[M], edge = 0;
int vis[N], match[N];
int n, m;

int id(int x, int y) {
    return (x - 1) * m + y;
}

int add(int a, int b) {
    p[++edge] = h[a]; v[edge] = b; h[a] = edge;
    p[++edge] = h[b]; v[edge] = a; h[b] = edge;
}

// 寻找已有的连成一片的陆地(岛屿),四周设为W
void dfsLands(int x, int y) {
    int i, nx, ny;
    if (vi[x][y]) return;
    vi[x][y] = 1;
    for (i = 0; i < 4; ++ i) {
        nx = x + dx[i];
        ny = y + dy[i];
        if (nx < 1 || nx > n || ny < 1 || ny > m || vi[nx][ny])
            continue;

        if (mp[nx][ny] == 'C') mp[nx][ny] = 'W';
        if (mp[nx][ny] == 'L') dfsLands(nx, ny);
    }
}

// 构图
void dfsClouds(int x, int y) {
    int i, nx, ny;
    if (vi[x][y]) return;
    vi[x][y] = 1;
    for (i = 0; i < 4; ++ i) {
        nx = x + dx[i];
        ny = y + dy[i];
        if (nx < 1 || nx > n || ny < 1 || ny > m || mp[nx][ny] != 'C')
            continue;

        add(id(x, y), id(nx, ny));
        dfsClouds(nx, ny);
    }
}

int hungary(int x) {
    if (vis[x]) return 0;
    vis[x] = 1;
    for (int i = h[x]; i; i = p[i])
        if (!match[v[i]] || hungary(match[v[i]])) {
            match[v[i]] = x;
            return 1;
        }
    return 0;
}

int main() {
    int i, j, ans = 0;
    scanf("%d%d", &n, &m);
    FOR(i,1,n) scanf("%s", mp[i] + 1);
    FOR(i,1,n) FOR(j,1,m) if (mp[i][j] == 'L' && !vi[i][j])
        dfsLands(i, j), ++ans;

    FOR(i,1,n) FOR(j,1,m) if (mp[i][j] == 'C')
        dfsClouds(i, j), ++ans;

    memset(match, 0, sizeof match);
    FOR(i,1,n) FOR(j,1,m) if ((i + j) % 2 == 0) {
        memset(vis, 0, sizeof vis);
        ans -= hungary(id(i, j));
    }
    printf("%d\n", ans);

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值