Java DFS求图连通分量大小时统计值恒为0的问题排查
问题根因
统计得到的连通分量大小始终为0,核心原因是Java基本类型为值传递:
- 主方法中定义的
size是基本类型局部变量,调用DFS时传入的是size的数值副本,而非变量本身的引用 - DFS内部对形参
s执行自增操作时,修改的仅为当前方法栈内的局部副本,所有递归层级的s各自独立,完全不会改动主方法里的原始size值,因此遍历结束后size始终是初始值0 - 原代码存在语法错误:DFS方法未写闭合右大括号,无法正常编译。
修复方案
最简洁的实现方式是调整DFS逻辑,让方法直接返回当前遍历连通块的总节点数,递归时逐层累加计数,从根源规避值传递带来的问题。
修正后可直接运行的完整代码如下:
import java.util.*; public class B { // 返回从节点v出发可遍历到的所有节点总数(即当前连通分量大小) static int dfs(int v, boolean[] visited, ArrayList<ArrayList<Integer>> adj) { visited[v] = true; int cnt = 1; // 计数初始为1,代表当前节点 for (int u : adj.get(v)) { if (!visited[u]) { cnt += dfs(u, visited, adj); // 累加邻接节点所在子连通块的节点数 } } return cnt; } public static void main(String[] args) { Scanner sc = new Scanner(System.in); final int MOD = 1000000007; int t = sc.nextInt(); while (t-- > 0) { int n = sc.nextInt(); int m = sc.nextInt(); ArrayList<ArrayList<Integer>> adj = new ArrayList<>(); for (int i = 0; i < n; i++) { adj.add(new ArrayList<>()); } boolean[] visited = new boolean[n]; for (int i = 0; i < m; i++) { int a = sc.nextInt() - 1; int b = sc.nextInt() - 1; adj.get(a).add(b); adj.get(b).add(a); } long res = 1; int groupCnt = 0; for (int i = 0; i < n; i++) { if (!visited[i]) { int size = dfs(i, visited, adj); groupCnt++; res = res * size % MOD; } } System.out.println(groupCnt + " " + res); } } }
改动点说明
- 移除DFS中无效的计数形参,改为方法内部维护计数变量,递归返回值直接传递连通块大小,不存在值传递导致的修改不可见问题
- 补全缺失的类导入、方法闭合括号等语法内容
- 优化取模运算逻辑,避免乘法过程中数值溢出
- 精简冗余代码,比如删除未被使用的
StringBuilder变量、无意义的Arrays.fill(visited, false)调用(boolean数组初始化默认值即为false)
内容的提问来源于stack exchange,提问作者Sudhanshu Singh
相关产品推荐
相关产品推荐

