Codeforces Gym 101201G Maximum Islands (dfs求联通块+最大独立集)


7958 Maximum Islands


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.


Input


The input fle contains several test cases, each of them as described below.
The frst line contains two space-separated integers 
and (≤ n; m ≤ 40).
Each of the next 
lines contains 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
For each test case, print, on a single line, a single integer indicating the maximum number of islands
that is consistent with the given grid.


Sample Input


5 4
LLWL
CCCC
CCCC
CCCC
LWLL


Sample Output


8 


题意:给你一个地图,L表示陆地,W表示水,C表示你可以任意安排,问最多有多少个陆地联通块。


思路:dfs求联通块过程中,把L的联通块用W,封装起来, 剩下的C求最大独立集就好了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 1e3 + 5;
char mp[maxn][maxn];
int id[maxn][maxn], match[maxn*maxn], vis[maxn][maxn], n, m, book[maxn*maxn];
vector<int> vt[maxn*maxn];
int dir[4][2] = {1, 0, -1, 0, 0, 1, 0, -1};
void dfs(int x, int y)
{
    vis[x][y] = 1;
    for(int k = 0; k < 4; k++)
    {
        int tx = x + dir[k][0];
        int ty = y + dir[k][1];
        if(tx < 0 || ty < 0 || tx >= n || ty >= m) continue;
        if(vis[tx][ty]) continue;
        if(mp[tx][ty] == 'L') dfs(tx, ty);
        if(mp[tx][ty] == 'C') mp[tx][ty] = 'W';
    }
}
int Find(int x)
{
    for(int i = 0; i < vt[x].size(); i++)
    {
        int to = vt[x][i];
        if(book[to]) continue;
        book[to] = 1;
        if(!match[to] || Find(match[to]))
        {
            match[to] = x;
            return 1;
        }
    }
    return 0;
}
int main()
{
    while(~scanf("%d%d", &n, &m))
    {
        int ans = 0;
        memset(match, 0, sizeof(match));
        memset(vis, 0, sizeof(vis));
        memset(id, 0, sizeof(id));
        for(int i = 0; i < maxn*maxn; i++)
            vt[i].clear();
        for(int i = 0; i < n; i++)
            scanf(" %s", mp[i]);
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                if(!vis[i][j] && mp[i][j] == 'L')
                    dfs(i, j), ans++;
            }
        }
        int cnt = 0;
        for(int i = 0; i < n; i++)
            for(int j = 0; j < m; j++)
                if(mp[i][j] == 'C')
                    id[i][j] = ++cnt;
        for(int i = 0; i < n; i++)
        {
            for(int j = 0; j < m; j++)
            {
                for(int k = 0; k < 4; k++)
                {
                    int tx = i + dir[k][0];
                    int ty = j + dir[k][1];
                    if(tx < 0 || ty < 0 || tx >= n || ty >= m) continue;
                    if(mp[tx][ty] == 'C')
                        vt[id[i][j]].push_back(id[tx][ty]);
                }
            }
        }
        int res = 0;
        for(int i = 1; i <= cnt; i++)
        {
            memset(book, 0, sizeof(book));
            if(Find(i)) res++;
        }
        ans += cnt-res/2;
        printf("%d\n", ans);
    }
    return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值