联通块的权:求解网格矩阵中联通块的最大权值

7-10 联通块的权

给出一个大小为n×m的网格矩阵,第i行第j列的单元格的权值为ai,j​。

若某个单元格权值不为0且其上下左右相邻的单元格同样不为0,则其构成一个联通块。

求该矩阵联通块的最大权值。

输入格式:

输入的第一行给出一个整数T——表示测试用例的数量。

接下来对于每一组测试用例,第一行给出两个整数n,m,表示网格矩阵的大小。
接下来n行,每行m个整数ai,j​——表示第i行第j列单元格的权值。

1≤T≤1000

1≤n,m≤1000

0≤ai,j​≤1000

输出格式:

对于每一组测试用例,单独一行输出一个整数——表示该矩阵中联通块的最大权值。

输入样例:

4
3 3
1 2 0
3 4 0
0 0 5
1 1
0
5 5
1 1 1 1 1
1 0 0 0 1
1 0 5 0 1
1 0 0 0 1
1 1 1 1 1
3 3
0 1 1
1 0 1
1 1 1

输出样例:

10
0
16
7

问题描述

给定一个大小为n×m的网格矩阵,每个单元格都有一个权值。如果某个单元格的权值不为0且其上下左右相邻的单元格同样不为0,则这些单元格构成一个联通块。我们需要找到矩阵中所有联通块的最大权值之和。

解题思路

这个问题可以通过广度优先搜索(BFS)或深度优先搜索(DFS)来解决。我的解法采用了BFS算法,具体步骤如下:

  1. ​初始化​​:读取输入数据,包括网格矩阵的大小和每个单元格的权值。
  2. ​遍历网格​​:对于每个未被访问过且权值大于0的单元格,启动BFS搜索。
  3. ​BFS搜索​​:从当前单元格出发,探索其上下左右的相邻单元格,将符合条件的单元格加入队列,并累加它们的权值。
  4. ​记录最大值​​:在每次BFS结束后,比较当前联通块的权值和与已知的最大值,更新最大值。
  5. ​输出结果​​:处理完所有测试用例后,输出每个测试用例的最大联通块权值。

关键点分析

  • ​BFS算法​​:适合处理网格中的联通块问题,能够有效地探索所有相连的单元格。
  • ​访问标记​​:使用一个标记数组D来记录哪些单元格已经被访问过,避免重复计算。
  • ​边界检查​​:在探索相邻单元格时,需要检查是否超出网格边界。
  • ​最大值更新​​:在每次BFS过程中实时更新当前联通块的权值和,并与全局最大值比较。

复杂度分析

  • ​时间复杂度​​:O(n×m),因为每个单元格最多被访问一次。
  • ​空间复杂度​​:O(n×m),用于存储网格矩阵和访问标记数组。

 

代码实现

#include<bits/stdc++.h>
using namespace std;
#define int long long
int b,c;
int C[1005][1005];
int D[1005][1005];
int xx[4]={0,1,0,-1};
int yy[4]={1,0,-1,0};
int snum=0;
int num;

struct node{
    int x,y;
}now,nextt;

void bfs(int x,int y)
{
    queue<node>q;
    now.x=x;
    now.y=y;
    q.push(now);
	D[x][y]=1;	
	num+=C[x][y];
	C[x][y]=0;
	snum=max(snum,num);
	while(!q.empty())
    { 
        now=q.front();
        q.pop();
    for(int i=0;i<4;i++)
	{
		int y1=now.y+yy[i];
	    int x1=now.x+xx[i];
		if(y1>0&&y1<=c&&x1>0&&x1<=b)
		{	
			if(D[x1][y1]==0&&C[x1][y1]>0)
			{
                D[x1][y1]=1;
                num += C[x1][y1];
                C[x1][y1]=0;
                 snum=max(snum,num);
                nextt.x=x1;
                nextt.y=y1;
				q.push(nextt);
			}
		}
		
	    }
    }
	
}
signed main()
{
	int a;
	cin>>a;

	while(a--)
	{
		snum=0;
		cin>>b>>c;
		for(int i=1;i<=b;i++)
		{
			for(int j=1;j<=c;j++)
			{
				cin>>C[i][j];
				D[i][j]=0;
			}
		}
		for(int i=1;i<=b;i++)
		{
			for(int j=1;j<=c;j++)
			{
				if(C[i][j]>0&&D[i][j]==0)
				{
					num=0;
					bfs(i,j);
				}
			}
		} 
		
		cout<<snum<<endl;
	}
	return 0;
}

总结

希望这篇博客能够帮助大家理解如何用BFS解决联通块问题。如果有任何疑问或建议,欢迎在评论区留言讨论。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值