连通块(dfs)

连通块(dfs)

题目描述
为了增强幼儿园小朋友的数数能力,小虎的老师给了一个家庭游戏作业。让小虎拿一块空的围棋盘,随机的在一些方格中放些棋子(有黑白两种颜色),如果一个方格和它的上、下、左、右四个方格之一有相同颜色的棋子,则认为两格子是相连通的。这期间,要求小虎不断统计共有多少个连通块。
如下图是一个5*9的一块棋盘,其中’.’表示空格,’*’表示黑棋子,’@’表示白棋子。则有4块连通的棋子块。
………
..**..@..
.**@@.@@.
..*@..*..
………
哥哥大虎在一边看一边想,如果棋盘是N*N的,共放了M个棋子,如何用计算机解决这个问题呢?
输入
第一行两个整数:N M
接下来有M行,每行三个正整数: C X Y (0<=C<=1, 1<=X,Y<=N)。分别表示依次放入棋子的颜色(0表示白色,1表示黑色)、要放入格子的横坐标和格子的纵坐标。
输出
共M行。第i行一个整数,表示放入第i个棋子后,当前有多少个棋子连通块。
样例输入 Copy
【样例1】
3  5
1  1  1
1  1  2
0  2  2
1  3  1
1  2  1
【样例2】
3  5
1  1  2
1  2  1
1  3  2
1  2  3
1 2 2
样例输出 Copy
【样例1】
1
1
2
3
2
【样例2】
1
2
3
4
1
提示
30%数据:1<=N<=10
60%数据:1<=N<=100
100%数据:1<=N<=500  1<=M<=N*N。
思路:每次添加,看四周是否存在棋子。若存在ans–;否则ans++;
#pragma GCC optimize(3 , "Ofast" , "inline")
 
#include <bits/stdc++.h>
 
#define rep(i , a , b) for(register int i=(a);i<=(b);i++)
#define rop(i , a , b) for(register ll i=(a);i<(b);i++)
#define per(i , a , b) for(register ll i=(a);i>=(b);i--)
#define por(i , a , b) for(register ll i=(a);i>(b);i--)
 
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<ll , ll> pi;
const int maxn = 555;
int e[maxn][maxn];
int v[maxn][maxn];
int n,m;
int dx[4]={0,0,1,-1};
int dy[4]={1,-1,0,0};
int x,y,z;
 
template<class T>
inline void read (T &x) {
    x = 0;
    int sign = 1;
    char c = getchar ();
    while (c < '0' || c > '9') {
        if ( c == '-' ) sign = - 1;
        c = getchar ();
    }
    while (c >= '0' && c <= '9') {
        x = x * 10 + c - '0';
        c = getchar ();
    }
    x = x * sign;
}
 
bool dfs(int x,int y,int id) {
    if(x<1||x>n) return false;
    if(y<1||y>n) return false;
    if(v[x][y]==id) return false;
    if(e[x][y]!=z) return false;
    v[x][y]=id;
    rep (i,0,3) dfs (x+dx[i],y+dy[i],id);
    return true;
}
int main () {
    read (n);read (m);
    int ans = 0;
    rep (i,1,m) {
        read (z);read (x);read (y);
        z++;
        if(dfs (x+1,y,i)) ans--;
        if(dfs (x-1,y,i)) ans--;
        if(dfs (x,y+1,i)) ans--;
        if(dfs (x,y-1,i)) ans--;
        ans++;
        v[x][y]=i;
        e[x][y]=z;
        printf ("%d\n",ans);
    }
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值