Educational Codeforces Round 5 C. The Labyrinth BFS,并查集

题目链接:见这里
C. The Labyrinth
time limit per test
1 second
memory limit per test
256 megabytes
input
standard input
output
standard output

You are given a rectangular field of n × m cells. Each cell is either empty or impassable (contains an obstacle). Empty cells are marked with ‘.’, impassable cells are marked with ‘*’. Let’s call two empty cells adjacent if they share a side.

Let’s call a connected component any non-extendible set of cells such that any two of them are connected by the path of adjacent cells. It is a typical well-known definition of a connected component.

For each impassable cell (x, y) imagine that it is an empty cell (all other cells remain unchanged) and find the size (the number of cells) of the connected component which contains (x, y). You should do it for each impassable cell independently.

The answer should be printed as a matrix with n rows and m columns. The j-th symbol of the i-th row should be “.” if the cell is empty at the start. Otherwise the j-th symbol of the i-th row should contain the only digit —- the answer modulo 10. The matrix should be printed without any spaces.

To make your output faster it is recommended to build the output as an array of n strings having length m and print it as a sequence of lines. It will be much faster than writing character-by-character.

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.
Input

The first line contains two integers n, m (1 ≤ n, m ≤ 1000) — the number of rows and columns in the field.

Each of the next n lines contains m symbols: “.” for empty cells, “*” for impassable cells.
Output

Print the answer as a matrix as described above. See the examples to precise the format of the output.
Examples
Input

3 3
.
.*.
.

Output

3.3
.5.
3.3

Input

4 5
*..
..*
...
..*

Output

46..3
..732
.6.4.
5.4.3

Note

In first example, if we imagine that the central cell is empty then it will be included to component of size 5 (cross). If any of the corner cell will be empty then it will be included to component of size 3 (corner).

题意:给你n行m列的矩阵,矩阵*表示障碍,.表示空地。对于每一个障碍,让你输出去掉这个障碍之后,这个点所在的连通块的大小是多少。答案需要%10。
解题方法:这个块的联通块大小,实际上是由四个部分所组成的,上下左右的连通块加在一起就好了,但是有一个问题,就是你有可能加重复,所以我们需要有个vis处理。之前比赛的时候用set写的,然后又改成带权dsu写了一发。

bfs + dsu:

//CF 616C
//GTMD dsu
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1150;
//const int maxm = 1e6+70;//WA
const int maxm = 1010050;//AC
char s[maxn][maxn];
int dir[4][2] = {{0, 1}, {0, -1}, {-1, 0}, {1, 0}};
int n, m, vis[maxm];
int getid(int x, int y){return x*m + y;}
namespace dsu{
    int fa[maxm], num[maxm];
    inline void init(){for(int i = 0; i <= getid(n, m) + 5; i++) fa[i] = i, num[i] = 1;}
    inline int find_set(int x){if(x == fa[x]) return x; else return fa[x] = find_set(fa[x]);}
    inline void union_set(int x, int y){int fx = find_set(x), fy = find_set(y); if(fx != fy){fa[fx] = fy; num[fy] = num[fx] + num[fy];}}
}
using namespace dsu;

int main()
{
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) scanf("%s", s[i] + 1);
    init();
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(s[i][j] == '*') continue;
            for(int k = 0; k < 4; k++){
                int tx = i + dir[k][0], ty = j + dir[k][1];
                if(tx < 1 || tx > n || ty < 1 || ty > m || s[tx][ty] == '*') continue;
                union_set(getid(tx, ty), getid(i, j));
            }
        }
    }
    for(int i = 1; i <= n; i++){
        for(int j = 1; j <= m; j++){
            if(s[i][j] == '.') printf(".");
            else{
                int ans = 1;
                for(int k = 0; k < 4; k++){
                    int tx = i + dir[k][0], ty = j + dir[k][1];
                    if(tx < 1 || tx > n || ty < 1 || ty > m || s[tx][ty] == '*') continue;
                    int idx = find_set(getid(tx, ty));
                    if(vis[idx] == 0){
                        vis[idx] = 1;
                        ans += num[idx];
                    }
                }
                printf("%d", ans%10);
                for(int k = 0; k < 4; k++){
                    int tx = i + dir[k][0], ty = j + dir[k][1];
                    if(tx < 1 || tx > n || ty < 1 || ty > m || s[tx][ty] == '*') continue;
                    int idx = find_set(getid(tx, ty));
                    vis[idx] = 0;
                }
            }
        }
        puts("");
    }
}

bfs+set

const int maxn = 1005;
#define Read(x) scanf("%d",&x)
char G[maxn][maxn];
int cnt[maxn*maxn];
int vis[maxn][maxn];
int dir[4][2]={{0,1},{0,-1},{-1,0},{1,0}};
int n,m;
set <int> S;
bool check(int x,int y)
{
    if(!vis[x][y]&&G[x][y]!='*'&&x>=0&&x<n&&y>=0&&y<m)
        return true;
    return false;
}
void dfs(int x,int y,int id)//标记联通块
{
    vis[x][y]=id;
    cnt[id]++;
    for(int k=0; k<4; k++)
    {
        int dx = x+dir[k][0];
        int dy = y+dir[k][1];
        if(check(dx,dy))
        {
            dfs(dx,dy,id);
        }
    }
}
int main()
{
    int id;
    Read(n),Read(m);
    for(int i=0;i<n;i++)
    {
        scanf("%s",G[i]);
    }
    id=0;
    memset(cnt,0,sizeof(cnt));
    for(int i=0; i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            if(G[i][j]=='.'&&!vis[i][j])
            {
                dfs(i,j,++id);
            }
        }
    }
    for(int i=0 ;i<n; i++)
    {
        for(int j=0; j<m; j++)
        {
            if(G[i][j]=='*')
            {
                int ans=0;
                for(int k=0;k<4;k++)
                {
                    int dx = i+dir[k][0];
                    int dy = j+dir[k][1];
                    S.insert(vis[dx][dy]);
                }
                for(set<int>::iterator it = S.begin();it != S.end(); it++)
                {
                    ans+=cnt[*it];
                }
                S.clear();
                ans++;ans%=10;
                printf("%d",ans);
            }
            else
                printf(".");
        }
        puts("");
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值