目录
前言
例题链接
什么是连通块
具体思路
代码
注意
__
前言
连通块问题属于图的深度优先遍历dfs,本文章通过求连通块的个数简单案例,来介绍dfs解决连通块问题。
例题中给到的是char类型地图,' . ' 代表不通路,' W ' 代表可连通,具体情况根据题目给的进行修改。
什么是连通块
如图整个表格为一个55二维数组,用来表示整个地图,白色填充为二维数组下标,最外层浅绿色代表地图的边界(为什么创建边界下文有提到),较为深颜色的为存放数据的二维数组,即下标(1~4)(1~4)。而颜色最深的块就是连通块,图中给出的就有三个连通块(上下左右连通,不考虑斜对连通)。
具体思路
除了行数列数以及开辟二维数组地图,还需要一个与地图同样大小的二维数组visitied,用来表示当前节点是否已经被访问过了。具体思路同图的dfs类似,当遍历到一个结点为1表示该节点可以连通(根据题目给的可能不同)并且没被访问过就进行深度遍历。
具体看代码。
代码
- import java.util.Scanner;
- /**
-
- 注意本例题中
-
- char[][]map地图 值为' . ' 代表不通,' W '代表可以连通
-
- int[][] visitied访问标记,初始值0未访问,1已访问
-
- @author lenovo
- *
- */
- public class Main {
- static int n,m,ans;
- static char[][] map;
- static int[][] vistied;
- static int[][] step= {{1,0},{0,1},{-1,0},{0,-1}};
- /*
-
- 上下左右移动遍历搜索
-
- 1 ,0 表示 x + 1 ,y + 0 向右移动,其他同理
-
- 如果为八向连通 则加上, { 1, 1 }, { 1, -1 }, { -1, 1 }, { -1, -1 } 代表斜向移动
- */
- public static void main(String[] args) {
- Scanner sc=new Scanner(System.in);
- n=sc.nextInt();
- m=sc.nextInt();
- map=new charn+2;
- vistied=new intn+2;
- //初始化地图,创建边界
- for (int i = 0; i <= n+1; i++) {
- mapi = '.';
- mapi = '.';
- }
- for (int i = 0; i <= m+1; i++) {
- map0 = '.';
- mapn+1 = '.';
- }
- //录入数据图(1~n)*(1~m)
- for (int i = 1; i <= n; i++) {
- String s=sc.next();
- int k=0;
- for (int j = 1; j <= m; j++) {
- mapi=s.charAt(k++);
- }
- }
- //从1-n 1-m一次遍历整张数据图
- for (int x = 1; x <=n; x++) {
- for (int y =1; y <=m; y++) {
- //如果当前节点为'W'可以连通 并且为被访问则说明存在一个连通块
- if(vistiedx ==0 && mapx == 'W') {
- ans++;//连接块数量+1
- vistiedx = 1;//当前节点标记为已经访问,以免重复判断
- dfs(x,y);//进行深度优先遍历,将与其连通的所有节点都标记为已经访问。
- //遍历完后从(1,1)到下一个节点(1,2)继续遍历,一次类推,直到所有节点全遍历完。
- }
- }
- }
- System.out.println(ans);
- }
- private static void dfs(int x, int y) {
- /**
-
- step.length - 1 = 3
-
- 0 1 2 3 四步代表上下左右均走一遍
- */
- for (int i = 0; i <=(step.length - 1); i++) {
- int newx=x+stepi; //x移动
- int newy=y+stepi;//y移动
- //如果移动后的节点 为 'W'可连通,并且未访问,则以移动后的节点为起点继续移动
- if(mapnewx =='W' && vistiednewx ==0) {
- vistiednewx = 1;//标记为已访问
- dfs( newx, newy);
- }
- }
- }
- }
注意
在实际应用时,为了防止当结点位于边界时,例如结点下标为(0,0),其左结点下标为(-1,0),这时-1会越界。因此开辟二维数组的大小总是比题目中给到的n*m多两行,即开辟(n+2)*(m+2)大小的二维数组。