AcWing 846. 树的重心(dfs)

这篇具有很好参考价值的文章主要介绍了AcWing 846. 树的重心(dfs)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

这是一道我一开始没怎么看懂的题目,然后后面看了y神的讲解就豁然开朗了

不过我们首先要有先置知识来理解这道题目

先置知识

邻接表:是一种表示图的数据结构,它通过链表的方式记录每个顶点及其相邻的顶点。在这个具体的问题中,使用数组 h 来表示邻接表。

  • h 数组:h 数组的每个元素 h[i] 是一个链表的头指针,指向以节点 i 为起点的链表的第一个元素。链表中的每个节点表示节点 i 可以直接连接的其他节点。
int h[N];
Arrays.fill(h, -1);

这段代码初始化了 h 数组,将每个顶点的链表头指针初始化为 -1,表示初始时每个顶点没有相邻的节点。

数组建立邻接表

int h[N], e[N * 2], ne[N * 2], idx;  // 数组范围要得是两倍才行
public static void add(int a, int b) {
    e[idx] = b;      // 将节点b添加到节点a的邻接表中
    ne[idx] = h[a];   // 更新节点a的邻接表头,将当前边的下一个节点设置为原来的邻接表头
    h[a] = idx++;     // 更新节点a的邻接表头为当前边的索引,并将索引自增
}
  • e 数组存储了图中边的终点,ne 数组存储了下一条边的索引,h 数组存储了每个节点的邻接表头。
  • idx 是一个全局变量,用于表示当前边的索引。
  • 在函数内部,首先将节点b添加到节点a的邻接表中(表示a指向b)。
  • 然后,更新节点a的邻接表头,将当前边的下一个节点设置为原来的邻接表头。
  • 最后,更新节点a的邻接表头为当前边的索引,并将索引自增,确保每次添加边都使用新的索引。

树的bfs模板

// 需要标记数组st[N],  遍历节点的每个相邻的便
void dfs(int u) {
    st[u] = true; // 标记一下,记录为已经被搜索过了,下面进行搜索过程
    for (int i = h[u]; i != -1; i = ne[i]) {
        int j = e[i];
        if (!st[j]) {
            dfs(j);
        }
    }
}

题目

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

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

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

输入格式

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

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

输出格式

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

数据范围

1≤n≤105文章来源地址https://www.toymoban.com/news/detail-787099.html

输入样例
9
1 2
1 7
1 4
2 8
2 5
4 3
3 9
4 6
输出样例:
4

代码与解析

import java.util.Arrays;
import java.util.Scanner;

public class Main {
    static final int N = 100010, M = N * 2;
    static int n;
    static int[] h = new int[N], e = new int[M], ne = new int[M];
    static int idx;
    static int ans = N;
    static boolean[] st = new boolean[N];

    public static void add(int a, int b) {
        e[idx] = b;
        ne[idx] = h[a];
        h[a] = idx++;
    }

    // 深度优先搜索,返回以u为根的子树的节点数
    public static int dfs(int u) {
        st[u] = true;  // 标记节点u已经被访问
        int size = 0, sum = 0;  // size记录u的最大子树节点数,sum记录u统领的所有子节点数
        for (int i = h[u]; i != -1; i = ne[i]) {  // 遍历节点u的所有邻接节点
            int j = e[i];  // j为u的邻接节点
            if (st[j]) {  // 如果j已经被访问过,继续下一个邻接节点
                continue;
            }
            int s = dfs(j);  // 递归调用dfs,计算以j为根的子树的节点数
            size = Math.max(size, s);  // 更新u的最大子树节点数
            sum += s;  // 累加u统领的所有子节点数
        }
        size = Math.max(size, n - sum - 1);  // 计算删除u后,剩余各个连通块中节点数的最大值
        ans = Math.min(size, ans);  // 更新全局最小值
        return sum + 1;  // 返回u节点+所有u节点统领的节点的综合
    }

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        n = sc.nextInt();  // 读取树的总节点数
        Arrays.fill(h, -1);  // 初始化每个节点的链表为空
        for (int i = 1; i < n; i++) {
            int a = sc.nextInt();
            int b = sc.nextInt();
            add(a, b);  // 添加一条从a到b的边
            add(b, a);  // 添加一条从b到a的边
        }
        dfs(1);  // 从节点1开始深度优先搜索
        System.out.println(ans);  // 输出最终结果
    }
}

到了这里,关于AcWing 846. 树的重心(dfs)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • [C++][算法基础]树的重心(树图DFS)

    给定一颗树,树中包含 n 个结点(编号 1∼n)和 n−1 条无向边。 请你找到树的重心,并输出将重心删除后,剩余各个连通块中点数的最大值。 重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心

    2024年04月12日
    浏览(39)
  • Acwing166 数独题解 - DFS剪枝优化

    166. 数独 - AcWing题库 数独 是一种传统益智游戏,你需要把一个 9×9 的数独补充完整,使得数独中每行、每列、每个 3×3 的九宫格内数字 1∼9 均恰好出现一次。 请编写一个程序填写数独。 搜索+剪枝(优化搜索顺序、位运算) 优化搜索顺序:很明显,我们肯定是从当前能填合法数字

    2024年03月10日
    浏览(50)
  • AcWing 93:递归实现组合型枚举 ← DFS

    【题目来源】 https://www.acwing.com/problem/content/95/ 【题目描述】 从 1∼n 这 n 个整数中随机选出 m 个,输出所有可能的选择方案。 【输入格式】 两个整数 n,m,在同一行用空格隔开。 【输出格式】 按照从小到大的顺序输出所有方案,每行 1 个。 首先,同一行内的数升序排列,

    2024年02月14日
    浏览(44)
  • AcWing 24:机器人的运动范围 ← BFS、DFS

    【题目来源】 https://www.acwing.com/problem/content/description/22/ 【题目描述】 地上有一个 m 行和 n 列的方格,横纵坐标范围分别是 0∼m−1 和 0∼n−1。 一个机器人从坐标 (0,0) 的格子开始移动,每一次只能向左,右,上,下四个方向移动一格。 但是不能进入行坐标和列坐标的数位之

    2024年02月14日
    浏览(33)
  • 【Acwing187】导弹防御系统(LIS+剪枝+贪心+dfs+迭代加深)

    1.最长上升子序列(lis)的算法思想和算法模板 2.acwing1010拦截导弹(lis+贪心)题解   本题题解,需要知道这种贪心算法 3.简单了解dfs暴力搜索、剪枝、搜索树等概念 dfs求最小步数有两种方法:记一个全局最小值,迭代加深 bfs的缺点:空间太大、不好剪枝 此处采用dfs的迭代

    2024年02月07日
    浏览(35)
  • 【AcWing刷题】蓝桥杯专题突破-广度优先搜索-bfs(11)

    目录 写在前面: 题目:844. 走迷宫 - AcWing题库 题目描述: 输入格式: 输出格式: 输入样例: 输出样例: 解题思路: 代码: AC !!!!!!!!!! 写在最后: 怎么样才能学好一个算法? 我个人认为,系统性的刷题尤为重要, 所以,为了学好广度优先搜索,为了用好搜

    2024年02月01日
    浏览(50)
  • 对无向图进行邻接矩阵的转化,并且利用DFS(深度优先)和BFS(广度优先)算法进行遍历输出, 在邻接矩阵存储结构上,完成最小生成树的操作。

    目录 一 实验目的 二 实验内容及要求 实验内容: 实验要求: 三 实验过程及运行结果 一 算法设计思路 二 源程序代码 三、截图 四 调试情况、设计技巧及体会 1.掌握图的相关概念。 2.掌握用邻接矩阵和邻接表的方法描述图的存储结构。 3.掌握图的深度优先搜索和广度优

    2024年02月04日
    浏览(57)
  • acwing算法提高之图论--最小生成树的扩展应用

    本专题用来记录使用最小生成树算法(prim或kruskal)解决的扩展题目。 题目1 :1146新的开始 C++代码如下, 题目2 :1145北极通讯网络 C++代码如下, 题目3 :346走廊泼水节 C++代码如下, 题目4 :1148秘密的牛奶运输 C++代码如下,

    2024年04月16日
    浏览(38)
  • acwing算法提高之图论--最小生成树的典型应用

    本专题用来记录使用prim算法或kruskal算法求解的题目。 题目1 :1140最短网络 C++代码如下, 题目2 :1141局域网 C++代码如下, 题目3 :1142繁忙的都市 C++代码如下, 题目4 :1143联络员 C++代码如下, 题目5 :1144连接格点 C++代码如下,

    2024年04月27日
    浏览(41)
  • 【蓝桥杯Java组】用Java带你暴走迷宫—DFS深度优先搜索

    📖📖 走迷宫 一类的问题一般都是暴力搜索解决,搜索的方法有两种:深度优先(DFS)和广度优先(BFS),而提到DFS就离不开递归,涉及到递归的问题理解起来还是有难度的,代码编写不当很容易造成栈溢出。 🌻🌻今天就用三道 走迷宫 问题带你彻底搞懂怎么用DFS秒杀迷宫

    2023年04月11日
    浏览(41)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包