搜索与图论-树与图的深度优先遍历

news2025/1/12 18:00:18

文章目录

  • 一、树与图的深度优先遍历
    • 1. 构造
    • 2. 遍历
    • 3. 具体实现详见例题——树的重心
  • 二、树与图的深度优先遍历例题——树的重心
    • 具体实现
      • 1. 样例演示
      • 2. 实现思路
      • 3. 代码注解
      • 4. 实现代码

DFS 深度优先遍历详见搜索与图论-DFS

一、树与图的深度优先遍历

  • 数与图的深度优先遍历与 DFS 类似,将树与图的各条分支给依次遍历一遍。其核心思想依然是递归,但是遍历对象变成了无向图。

1. 构造

  • 由于是无向图,它构建起来不同于普通的树,代码如下:
int e[N],ne[N],h[M];//M = 2 * N;
int idx;

void add(int a,int b)
{
    e[idx] = b,ne[idx] = h[a],h[a] = idx++;
}
  • 在输入时:
int a,int b;
cin >> a >> b;
add(a,b),add(b,a);
  • 由于是无向图,所以要 add 两次,如果是有向图,只需要按指向进行 add 即可。
  • add 函数与单链表插入头节点的函数类似,下面是单链表插入头节点的代码:
void head_add(int x)
{
    e[idx] = x,ne[idx] = head,head = idx++;  
}
  • 仅仅将 head 换成了 h 数组。
  • 而在无向图当中,h 和 ne 数组发挥的作用是不同的。h 是指向子节点的指针,用于递归部分,而 ne 搜索到结束时跳转回上一个分叉的零一个子节点的指针,用于循环。

2. 遍历

  • 如下所示的 DFS 函数框架代码:
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);
        }
    }
}

3. 具体实现详见例题——树的重心

二、树与图的深度优先遍历例题——树的重心

题目描述

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

输入格式

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

输出格式

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

数据范围

1 ≤ n ≤ 1e5

输入样例

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

输出样例

4

具体实现

1. 样例演示

  • 1 到 2 连一条边。
  • 1 到 7 连一条边。
  • 1 到 4 连一条边。
  • 2 到 8 连一条边。
  • 2 到 5 连一条边。
  • 4 到 3 连一条边。
  • 3 到 9 连一条边。
  • 4 到 6 连一条边。
  • 得到如下图所示的树:

在这里插入图片描述

  • 然后,我们依次遍历删除每一个节点,取出每次删除后的最大值,进行比较,得出其中的最小值输出。
  • 当我们删除 1 号点,便得到了三个连通块,分别为 { 2,5,8 } ,{ 4,5,6,9 },{ 7 } 。其中,最多的点数是 4 。
  • 后续过程同理。

2. 实现思路

  • 首先,我们需要弄清楚题目当中树的重心定义:重心是指树中的一个结点,如果将这个点删除后,剩余各个连通块中点数的最大值最小,那么这个节点被称为树的重心。
  • 这里需要注意的是,这里输出的不是重心编号,而是输出各个连通块中点数最小的最大值是多少,因为树的重心可能不唯一,但是这个数字是唯一的,通过这个数字比较好评测。
  • 在此,我们只需要在删除一个点后,从下往上统计其对应子节点所在连通块中点的个数和其上面父节点所在连通块中点的个数,然后进行比较即可。
  • 以删除 4 号点为例:

在这里插入图片描述

3. 代码注解

  • bool st[N];用于记录每个点是否被使用过。
  • 节点的编号是指上图所画的树中节点的值,范围是从1~n 。在本题中,每次输入的 a 和 b 就是节点的编号,编号用 e[i] 数组存储。
  • 节点的下标指节点在数组中的位置索引,数组之间的关系就是通过下标来建立连接,下标用 idx 来记录。 idx 范围从 0 开始,如果 idx==-1 表示空。
  • 详细注解在代码中标注了。

4. 实现代码

#include <bits/stdc++.h>
using namespace std;

const int N = 1e5 + 10; //数据范围是10的5次方
const int M = 2 * N; //以有向图的格式存储无向图,所以每个节点至多对应2n-2条边

int h[N]; //邻接表存储树,有n个节点,所以需要n个队列头节点
int e[M]; //存储元素
int ne[M]; //存储列表的next值
int idx; //单链表指针
int n; //题目所给的输入,n个节点
int ans = N; //表示重心的所有的子树中,最大的子树的结点数目

bool st[N]; //记录节点是否被访问过,访问过则标记为true

//a所对应的单链表中插入b  a作为根 
void add(int a, int b) 
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}

//返回以u为根的子树中节点的个数,包括u节点
int dfs(int u) 
{
    int res = 0; //存储 删掉某个节点之后,最大的连通子图节点数
    st[u] = true; //标记访问过u节点
    int sum = 1; //存储 以u为根的树 的节点数, 包括u,如图中的4号节点

    //访问u的每个子节点
    for (int i = h[u]; i != -1; i = ne[i])
    {
        int j = e[i];
        //因为每个节点的编号都是不一样的,所以用编号为下标 来标记是否被访问过
        if (!st[j])
        {
            int s = dfs(j);  // u节点的单棵子树节点数,如图中的size值
            res = max(res, s); // 记录最大联通子图的节点数
            sum += s; //以j为根的树 的节点数
        }
    }

    //n-sum 如图中的n-size值,不包括根节点4;
    res = max(res, n - sum); // 选择u节点为重心,最大的 连通子图节点数
    ans = min(res, ans); //遍历过的假设重心中,最小的最大联通子图的 节点数
    return sum;
}

int main()
{
    memset(h, -1, sizeof h); //初始化h数组 -1表示尾节点
    cin >> n; //表示树的结点数

    // 题目接下来会输入,n-1行数据,
    // 树中是不存在环的,对于有n个节点的树,必定是n-1条边
    for (int i = 0; i < n - 1; i++)
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a); //无向图
    }

    dfs(1); //可以任意选定一个节点开始 u<=n

    cout << ans << endl;
    system("pause");
    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/62807.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

JDK8新特性超详细总结

JDK8新特性 ​ Java 是第一大编程语言和开发平台。它有助于企业降低成本、缩短开发周期、推动创新以及改善应用服务。如今全球有数百万开发人员运行着超过 51 亿个 Java 虚拟机&#xff0c;Java 仍是企业和开发人员的首选开发平台 课程内容的介绍 了解Java发展史Lambda表达式…

DNS轮询是什么

参考文章&#xff1a;DNS轮询是什么&#xff1f; DNS轮询简单来说就是一个域名解析多个IP地址。那么为什么会有DNS轮询呢&#xff1f;一般DNS轮询用于访问量较大的网站&#xff0c;由于一台服务器无法承载&#xff0c;所以准备了多台服务器组成集群做负载均衡&#xff0c;这些服…

使用Mac编写Thirft的HelloWorld项目

前言 最近在hive新增Thirft接口&#xff0c;于是学习了一下Thirft的使用 步骤 准备工作 brew install thrift安装thrift创建maven项目并引入依赖 <dependency><groupId>org.apache.thrift</groupId><artifactId>libthrift</artifactId><v…

led护眼灯哪种品牌质量好?2022什么牌子的护眼灯最好推荐

现在绝大部分台灯都是使用led灯珠作为发光源&#xff0c;这不仅仅是led灯珠本身的优秀&#xff0c;也更是市场的选择&#xff0c;无论是光线照度、显色性&#xff0c;还是亮度、色温的可调控性&#xff0c;led护眼灯都有非常明显的优势&#xff0c;对保护眼睛起到非常大的作用。…

微信小程序开发平台

微信小程序开发平台顾名思义就是一个可以开发小程序的地方。 微信小程序开发平台&#xff1a;【电脑浏览器输入3M.FKW.COM了解详情】 适合群体&#xff1a;企业、机构、个体户 微信小程序开发平台方式&#xff1a; 自建——可以通过套用小程序模板&#xff0c;利用拖拽式小…

ADSP-21489的开发详解:VDSP+自己编程写代码开发(3-可能出现的故障和解决办法)

如果连接失败怎么办&#xff1f;软件报错&#xff0c;无法进入上图所示的状态&#xff1f;不用担心&#xff0c;ADI 的 Visual DSP软件提供了自带的 TEST 功能&#xff0c;能通过软件分析&#xff0c;得出故障原因&#xff0c;并排除。 发现 ADI 仿真器连不上开发板&#xff0c…

浏览器执行过程与V8引擎执行原理(无惧面试)

前言&#xff1a;一文带你理解&#xff0c;浏览器渲染过程以及V8引擎背后执行原理&#xff0c;让你知道页面在浏览器上显示出来背后都做了什么事情。这将是一个js高级系列第一篇&#xff0c;这将会为之后的闭包&#xff0c;作用域链&#xff0c;原型等让人迷惑的知识打基础。感…

使用IDEA 进行 安卓开发

使用IDEA 进行 安卓开发 前言 以前使用Eclipse 进行 Android 开发&#xff0c;感觉对新手来说实在是太不友好了&#xff0c;又是Android SDK&#xff0c;有是配 gradle 等一系列的东西&#xff0c;对与新手而言&#xff0c;总是遗漏。或者版本对不上&#xff0c;一堆问题&…

.net core 读取配置的几种方式

json配置文件示例 {"Logging": {"LogLevel": {"Default": "Information","Microsoft.AspNetCore": "Warning"}},"Account": {"username": "zhangsan","password":&quo…

arXiv2022-12 | FLIP:Scaling Language-Image Pre-training via Masking

凯明团队新作。 论文地址&#xff1a;https://arxiv.org/abs/2212.00794 一、问题 Even using high-end infrastructures, the wall-clock training time is still a major bottleneck hindering explorations on scaling vision-language learning. 即使使用高端的基础设施…

人工智能:声纹相关基础概念介绍

❤️作者主页&#xff1a;IT技术分享社区 ❤️作者简介&#xff1a;大家好,我是IT技术分享社区的博主&#xff0c;从事C#、Java开发九年&#xff0c;对数据库、C#、Java、前端、运维、电脑技巧等经验丰富。 ❤️个人荣誉&#xff1a; 数据库领域优质创作者&#x1f3c6;&#x…

移动端开发——APP端上H5容器化建设

1. 背景 当前移动端和前端的结合愈加紧密&#xff0c;尤其是在偏重活动运营的电商App中&#xff0c;受制于App版本审核&#xff0c;具备研发成本低、可灵活发布等特点的H5页面受到青睐&#xff0c;使其在APP端上承接了越来越多的业务。然而H5页面本身也存在一些亟需解决的问题…

nginx配置错误三例漏洞-

路径&#xff1a;nginx/insecure-configuration 运行成功后&#xff0c;Nginx将会监听8080/8081/8082三个端口&#xff0c;分别对应三种漏洞。 8080&#xff1a;CRLF注入漏洞 8081&#xff1a; 目录穿越漏洞 8082&#xff1a; add_header被覆盖 $uri导致的CRLF注入漏洞 Nginx…

股票分时成交明细接口的数据怎么看?

今天的文章我们主要针对于股票日线级别的行情数据&#xff0c;介绍了一些获取和处理的方法&#xff0c;其实最原始的数据是交易明细数据&#xff0c;level2行情软件的各种周期和统计的数据都是通过明细数据跨周期转换而形成的&#xff0c;比如分钟K线、小时K线、当日成交量、成…

基于STM32蓝牙控制的app智能台灯设计

提示&#xff1a;记录毕设 文章目录前言一、任务书1.1设计(研究)目标:1.2设计(研究)内容:二、代码思路三、硬件设计3.1总体设计3.2蓝牙部分设计四、联系我们五、部分代码喜欢请点赞哦&#xff01;前言 基于STM32蓝牙控制的app智能台灯设计&#xff0c;主控使用STM32F103ZET6&a…

web服务器及IDEA部署Tomcat服务器

目录 一、程序开发体系结构 1.1 C/S体系结构 1.2 B/S体系结构 二、Web服务器 2.1 概念 2.1.1 什么是Web 2.1.2 什么是Web服务器 2.2 常见Web服务器 2.3 Tomcat服务器 2.3.1 Tomcat的下载 2.3.2 Tomcat的安装 2.3.3 Tomcat的目录结构 2.3.4 Tomcat的启动 2.3.5 To…

MFC树控件的属性和初始化(基于对话框的编程)

目录 一、控件属性 1.找控件Tree Control 2.Has Lines和Has Buttons属性 3.Lines At Root属性 二、代码操作Tree Control显示内容 1.添加Tree Control变量 2.在OnInitDialog中添加初始化代码 3.设置图标 3.1导入icon 3.2 写入加载图片代码 3.3添加节点 4.设置默认选…

抗击疫情静态HTML网页作业作品 大学生抗疫感动专题页设计制作成品 简单DIV CSS布局网站

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

HTML期末大作业(HTML+CSS+JavaScript响应式游戏资讯网站bootstrap网页)

&#x1f389;精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业…

12月5日:thinkphp模板

今天学习ThinkPHP中的模板部分内容 接口开发&#xff0c;看不到dom结构&#xff0c;页面信息都是通过js或者一些其他技术引入 模板&#xff1a;是用来渲染前端页面&#xff0c;在后端的api接口开发中并不会常用到模板&#xff0c;但是后台管理页面却会使用MVC模式开发&#xf…