ACWing 树的重心

95 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1条无向边。

请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。

重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。

输入格式

第一行包含整数 n,表示树的结点数。

接下来 n−1行,每行包含两个整数 ab,表示点 a 和点 b之间存在一条边。

输出格式

输出一个整数 m,表示将重心删除后,剩余各个连通块中点数的最大值。

数据范围

1≤n≤105

输入样例

9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6

输出样例:

4

二、思路分析:

  1. 这一到题目考察是深度优先遍历,树图的储存方式

  2. 合理的使用数据结构存放图:比如邻接表和邻接矩阵

三、AC 代码:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.Scanner;

public class acwing_846 {
    /** 树的节点 */
    public static int N;
    /** 是否访问过该节点 */
    public static boolean[] visted = null;
    /** 删除重心的最大节点数 */
    public static int ans = 0;
    /** 邻接表 */
    public static ArrayList<ArrayList<Integer>> th = new ArrayList<>();

    public static void main(String[] args) {
        Scanner in = new Scanner(System.in); 
        
        /** 定义树大小 */
        ans = N = in.nextInt(); 
        /** 初始化邻接表 */
        for (int i = 0; i < N + 1; i++) {
            th.add(new ArrayList<Integer>());
        }
        /** 初始化访问节点 */
        visted = new boolean[N + 1];
        /** 输入树 */
        for (int i = 0; i < N - 1; i++) {
            int a = in.nextInt();
            int b = in.nextInt();

            /**  树是无环无向边*/
            th.get(a).add(b);
            th.get(b).add(a);
        }
        dfs(1);
        System.out.println(ans);
        in.close();
    }

    /**
     * 深度优先遍历
     * @param u 起始节点
     * @return sum + 1 当前子树节点数
     */
    public static int dfs(int u){
        /** 设置访问节点为true */
        visted[u] = true;
        int size = 0 , sum = 1;

        Iterator<Integer> iterator = th.get(u).iterator();
        while(iterator.hasNext()){
            Integer next = iterator.next();
            if(!visted[next]){
                int s = dfs(next);
                size = Math.max(size,s);
                sum += s;
            }
        }
        size = Math.max(size, N - sum );

        ans = Math.min(ans, size);
        return sum;
    }
}

四、总结:

我们使用深度优先遍历,一般都是进行递归。我们需要理解每一步的规律,总结通式