文章目录
- 例题
- 846. 树的重心(深度优先遍历 / 树形DP)⭐⭐⭐⭐⭐🚹🚹🚹🚹🚹(重要!好题!)
- 847. 图中点的层次
- 相关链接
要学会建树、建图的通用方法。
dfs 和 bfs 的代码框架。
例题
846. 树的重心(深度优先遍历 / 树形DP)⭐⭐⭐⭐⭐🚹🚹🚹🚹🚹(重要!好题!)
https://www.acwing.com/problem/content/848/
在 dfs 的过程中,统计各个节点作为断点时的连通块最大值。
import java.util.*;public class Main {static List<Integer>[] g;static int ans = Integer.MAX_VALUE, n = 0;public static void main(String[] args){Scanner scanner = new Scanner(System.in);n = scanner.nextInt();g = new ArrayList[n + 1];Arrays.setAll(g, e -> new ArrayList<Integer>());for (int i = 0; i < n - 1; ++i) {int a = scanner.nextInt(), b = scanner.nextInt();g[a].add(b);g[b].add(a);}dfs(1, 0); // 为什么要用dfs?因为dfs可以求出子树的大小System.out.println(ans);}static int dfs(int x, int fa) {// res记录删除该节点之后各个连通块中点数的最大值;sum记录该节点为根节点时所在连通块点的数量int res = 0, sum = 1;for (int y: g[x]) {if (y != fa) {int s = dfs(y, x); // 枚举各个x的子节点y作为根节点时的连通块大小res = Math.max(res, s);sum += s;}}res = Math.max(res, n - sum); // n - sum 是 x 的父节点以上的那个连通块的大小ans = Math.min(ans, res);return sum;}
}
847. 图中点的层次
https://www.acwing.com/problem/content/849/
看到最短距离就可以想到使用宽搜。
注意!
:题目中说明了 a 和 b 表示存在一条从 a 走到 b 的边,即这是一个有向图。在建图的过程中,对于每一行只需要添加一条路径就可以了。
import java.util.*;public class Main {static List<Integer>[] g;static int n, m;public static void main(String[] args){Scanner scanner = new Scanner(System.in);n = scanner.nextInt();m = scanner.nextInt();g = new ArrayList[n + 1];Arrays.setAll(g, e -> new ArrayList<Integer>());for (int i = 0; i < m; ++i) {int a = scanner.nextInt(), b = scanner.nextInt();g[a].add(b); // 只需要添加从 a 走到 b 的路径}System.out.println(bfs());}static int bfs() {Queue<Integer> q = new LinkedList<>();boolean[] st = new boolean[n + 1];q.offer(1);st[1] = true;int ans = 0;while (!q.isEmpty()) {int sz = q.size();for (int i = 0; i < sz; ++i) {int x = q.poll();if (x == n) return ans;for (int y: g[x]) {if (!st[y]) {st[y] = true;q.offer(y);}}}++ans;}return -1;}
}
相关链接
更多关于树形 DP 可见:
【算法】树形DP ①(树的直径)
【算法】树形DP ② 打家劫舍Ⅲ(树上最大独立集)
【算法】换根DP