# 01矩阵之连通块(连通块数量,点数最大的连通块点数)

最大联通(蓝桥杯题)

01矩阵中点数最大的连通块点数

思路如下:我们用for循环遍历01矩阵,当遍历到1时,标记该点(表示已经搜过了),让color-=1(color是用来染色的,表示这是哪个连通块),
然后进入dfs(x,y,color)。dfs的作用是搜索与当前这个点(x,y)相邻的点(上下左右)。
dfs的实现在代码中解释
其中最关键的就是color的取法,取好了能简化很多代码。
AC代码如下:

#include <bits/stdc++.h>
using namespace std;

int main()
{
  cout << 148;
}

(bushi

实现代码如下:(DFS)

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> PII;
int a[30+2][60+2];//存地图
int num;//用来染色的
int cnt[32*62];//存连通块中1的点数
bool col[32][62];//标记该点有没有搜过

void dfs(int x,int y,int color)
{
	//之间对该个连通块++,说明该点在该连通块中
    cnt[-color]++;//为什么color要取负,请先看主函数中color是如何取值的
    a[y][x] = color;
    //方向变量
    int dx[4] = {0,0,1,-1};
    int dy[4] = {1,-1,0,0};
    //对上下左右每个点都搜一遍(类似bfs)
        for(int i = 0;i<4;i++)
        {
            int tx = x + dx[i];
            int ty = y + dy[i];
            if(tx>=1&&tx<=60&&ty>=1&&ty<=30)
            {
                if(a[ty][tx]>0&&col[ty][tx]==0)
                {
                	//标记该店已经搜过了,否则在下一个dfs中会搜回来
                    col[ty][tx] = 1;
                    dfs(tx,ty,color);//继续搜tx,ty上下左右的点
                }
            }
        }
}



int main()
{
    
    string s;
    for(int i = 1;i<=30;i++)
    {
        cin >> s;//之间cin >> a[i][j]的话不能达到存地图的目的,会将第一行的01当作一个数输入进a[1][1]。
        for(int j = 1;j <= 60;j++)
        {
            a[i][j] = s[j-1] - '0';
        }
    }
    
    int mmax = 0;//用来保存最大的连通块点数
    for(int i = 1;i<=30;i++)
    for(int j = 1;j<=60;j++)
    if(a[i][j]>0)//如果找到了1(这就是体现color取值的好处的地方,因为num--,所以染色一定会染成负数,只有1是>0的,所以只需要一个判断,就能找出没被搜过的1)
    {
        num--;//每找到一个新的连通块,就--得到新的染色值,由于是负数,所以dfs中color要取负
        col[i][j] = 1;//标记,表示搜过了
        dfs(j,i,num);//彻底搜索该点所在的连通块
        mmax = max(mmax,cnt[-num]);//找最大的连通块点数
    }
    cout << mmax;//输出点数,同理,如果想知道01矩阵中连通块数量的话,只需要输出-num即可。
}

01矩阵中连通块数量

其实上面的代码也可以实现求01矩阵中连通块的数量,但是上面代码用的是dfs,这里我使用bfs实现
思路与上面代码相似,

代码如下:

#include <bits/stdc++.h>
using namespace std;

typedef pair<int,int> PII;
int a[30+2][60+2];
int num;//用来染色的
int cnt[32*62];
bool col[32][62];
PII q[32*62];

void bfs(int x,int y,int color)
{
    cnt[-color]++;//点数+1
    a[y][x] = color;//染色
    int hh = 0,tt = -1;//数组模拟队列
    q[++tt] = {x,y};//存当前的点
    //方向变量
    int dx[4] = {0,0,1,-1};
    int dy[4] = {-1,1,0,0};
    while(hh<=tt)//遍历队列
    {
    	//col[ty][tx] = 1;//不能在这里表示搜过了,由于bfs是宽度优先搜索,在这里标记的话会多搜很多次!!!
        auto t = q[hh++];
        //搜4个方向
        for(int i = 0;i<4;i++)
        {
            int tx = t.first + dx[i];
            int ty = t.second + dy[i];
            //满足条件
            if(tx>=1&&tx<=60&&ty>=1&&ty<=30)
            if(col[ty][tx]==0&&a[ty][tx]>0)
            {
            //则存点
                q[++tt] = {tx,ty};
                //连通块点数+1
                cnt[-color]++;
                //给该点染色
                a[ty][tx] = color;
                //一定要在这里表示该点搜过了!!!
                col[ty][tx] = 1;//这里很重要!!!
            }
        }
    }
}



int main()
{
    
    string s;
    for(int i = 1;i<=30;i++)
    {
        cin >> s;
        for(int j = 1;j <= 60;j++)
        {
            a[i][j] = s[j-1] - '0';
        }
    }
    
    int mmax = 0;
    for(int i = 1;i<=30;i++)
    for(int j = 1;j<=60;j++)
    if(a[i][j]>0)
    {
        num--;
        col[i][j] = 1;
        bfs(j,i,num);
        mmax = max(mmax,cnt[-num]);
    }
    
    cout << -num;//连通块数量
    //for(int i = 1;i<=-num;i++)cout << cnt[i] << '\n';//这是我debug的语句·-·
}

❀完结撒花❀

  • 8
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值