树与图的深度优先遍历(dfs的图论中的应用)

模板题

846. 树的重心

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

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

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

输入格式

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

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

输出格式

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

数据范围

1≤n≤10^5

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

这道题的比较坑的点是题意很难理解,拿测试用例举例:

拿两个节点1和4举例,先看节点1

如果把节点1拿掉,那么剩余的联通块2、4、7点数分别是:3、4、1,那么删除节点1后连通块点数的最大值就是4

把节点4拿掉,剩余的连通块就是 :1、3、6,当中的点数分别是:5、2、1,那么删除节点4后剩余连通块节点数的最大值就是5

就这样一直找下去,那么值最小的就是重心,因为出题人偷懒重心有可能有多个不好判断对错,他就改成输出了删除重心后连通块点数的最大值

代码:

#include <iostream>
#include <vector>

using namespace std;

const int N = 1e5 + 10;
bool st[N];
vector<int> e[N];

int n;
int res = 0x3f3f3f3f;

int dfs(int u){
    st[u] = true;
    
    int size = 0,sum = 1;
    for(auto x : e[u]){
        if(st[x]) continue;
        
        int t = dfs(x);
        size = max(size,t);
        sum += t;
    }
    
    size = max(size,n - sum);
    res = min(res,size);
    
    return sum;
}

int main()
{
    cin >> n;
    for(int i = 0,a,b;i < n - 1;i ++){
        cin >> a >> b;
        e[a].push_back(b),e[b].push_back(a);
    }
    
    dfs(1);
    
    cout << res << endl;
    
    return 0;
}

树的直径

题目描述

给定一棵 n 个结点的树,树没有边权。请求出树的直径是多少,即树上的最长路径长度是多少。

输入格式

第一行输入一个正整数 n,表示结点个数。

第二行开始,往下一共 n−1 行,每一行两个正整数 (u,v),表示一条边。

输出格式

输出一行,表示树的直径是多少。

输入输出样例

输入 #1复制

5
1 2
2 4
4 5
2 3

输出 #1复制

3

说明/提示

数据保证,1≤n≤10^5。

这道题的思路是,随便从一个点出发(我是从1找的)然后找到最底下的点记为target,这个点一定是树的某一边的最下面,那么从target开始,它能到达的最远位置就是直径了

代码:

#include <iostream>
#include <vector>
#include <cstring>

using namespace std;

const int N = 1e5 + 10;
bool st[N];
vector<int> e[N];

int n;
int max_dep = 0,target = 1;

void dfs1(int u,int dep)
{
    st[u] = true;

    if(dep > max_dep){
        max_dep = dep;
        target = u;
    }

    for(auto x : e[u]){
        if(st[x]) continue;
        dfs1(x, dep + 1);
    } 
}

int dfs2(int u){
    st[u] = true;

    int sum = 0;
    for(auto x : e[u]){
        if(st[x]) continue;

        sum = max(sum,dfs2(x) + 1);
    }

    return sum;
}

int main()
{
    cin >> n;
    for(int i = 0,a,b;i < n - 1;i ++){
        cin >> a >> b;
        e[a].push_back(b),e[b].push_back(a);
    }

    dfs1(1,0);

    // cout << target << endl;

    memset(st,false,sizeof(st));

    cout << dfs2(target) << endl;

    return 0;
}

核心城市

题目描述

X 国有 n 座城市,n−1 条长度为 1 的道路,每条道路连接两座城市,且任意两座城市都能通过若干条道路相互到达,显然,城市和道路形成了一棵树。

X 国国王决定将 k 座城市钦定为 X 国的核心城市,这 k 座城市需满足以下两个条件:

  1. 这 k 座城市可以通过道路,在不经过其他城市的情况下两两相互到达。
  2. 定义某个非核心城市与这 k 座核心城市的距离为,这座城市与 k 座核心城市的距离的最小值。那么所有非核心城市中,与核心城市的距离最大的城市,其与核心城市的距离最小。你需要求出这个最小值。

输入格式

第一行 2 个正整数 n,k。

接下来 n−1 行,每行 2 个正整数 u,v 表示第 u 座城市与第 v 座城市之间有一条长度为 1 的道路。

数据范围:

  • 1≤k<n≤10^5
  • 1≤u,v≤n,u≠v,保证城市与道路形成一棵树。

输出格式

一行一个整数,表示答案。

输入输出样例

输入 #1复制

6 3
1 2
2 3
2 4
1 5
5 6

输出 #1复制

1

说明/提示

【样例说明】

钦定 1,2,5这 3 座城市为核心城市,这样 3,4,6 另外 3 座非核心城市与核心城市的距离均为 1,因此答案为 1。

这道题是树的直径的应用,首先题目要找到k个核心城市,那么我们先拆分问题,如果只要一个核心城市应该找那个?是不是应该找中心点(也就是树的直径的中点),这样是不是距离就一定是最小值,那么如果再找剩余的k - 1个呢?由于题目是找最小值,那么我们只要求出前k个最大的距离,然后遍历后n - k个距离就是答案了

我们以一棵树举例

算出直径是5后,找中心点

确定1是中心点,那么我们可以先算出每个点的深度(蓝色)

其次在算出每个点能达到的最大深度(紫色)

发现规律了吗?中心点的与非核心城市的距离一定是最大的,其次我们找出前k个与非核心城市距离大的点选做核心城市,然后从非核心城市当中算一下距离即可

代码:

#include <iostream>
#include <vector>
#include <cstring>
#include <algorithm>
#include <queue>

using namespace std;

const int N = 1e5 + 10;
int deep[N],dist[N],f[N];
bool st[N];
vector<int> path,e[N];


int n, k;
int l = 1, r = 1, max_dep = 0;
int D = 0,center;

void dfs1(int u, int dep) {
    st[u] = true;
    if (max_dep < dep) {
        max_dep = dep;
        l = u;
    }

    for (auto x : e[u]) {
        if (st[x]) continue;
        dfs1(x, dep + 1);
    }
}

void dfs2(int u, int d) {
    st[u] = true;
    if (D < d) D = d, r = u;

    for (auto x : e[u]) {
        if (st[x]) continue;
        dfs2(x, d + 1);
    }
}

void find(int u, int target){
    st[u] = true;
    path.push_back(u);

    if(u == target) return;

    for(auto x : e[u]){
        if(st[x]) continue;

        find(x,target);

        if(path.back() == target) return;
    }

    path.pop_back();
}

void bfs(int u)
{
    memset(deep,-1,sizeof(deep));
    deep[u] = 0;
    queue<int> q;
    q.push(u);

    while(!q.empty()){
        auto v = q.front();
        q.pop();

        for(auto x : e[v]){
            if(deep[x] == -1){
                deep[x] = deep[v] + 1;
                q.push(x);
            }
        }
    }
}

int dfs(int u){
    st[u] = true;
    int sum = deep[u];

    for(auto x : e[u]){
        if(st[x]) continue;

        int t = dfs(x);
        sum = max(sum,t);
    }

    dist[u] = sum;
    return sum;
}

bool cmp(int a,int b){
    return a > b;
}

int main() {
    cin >> n >> k;
    for (int i = 0, a, b; i < n - 1; i++) {
        cin >> a >> b;
        e[a].push_back(b),e[b].push_back(a);
    }

    dfs1(1, 0);

    memset(st,false,sizeof(st));
    dfs2(l, 0);
    // cout << "边界点:" << l << " " << r << endl;
    // cout << "直径:" << D << endl;

    memset(st,false,sizeof(st));
    find(l,r);
    int size = path.size();
    center = path[size / 2];
    // cout << "中间点: " << center << endl;

    bfs(center);

    memset(st,false,sizeof(st));
    dfs(center);
    for(int i = 1;i <= n;i ++) f[i] = dist[i] - deep[i];

    sort(f + 1,f + n + 1,cmp);
    // for(int i = 1;i <= n;i ++) cout << f[i] << " ";
    // cout << endl;
    int res = -1;
    for(int i = k + 1;i <= n;i ++) res = max(res,f[i] + 1);
    cout << res << endl;

    return 0;
}

加油

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

7天速成前端 ------学习日志 (继苍穹外卖之后)

前端速成计划总结&#xff1a; 全26h课程&#xff0c;包含html&#xff0c;css&#xff0c;js&#xff0c;vue3&#xff0c;预计7天内学完。 起始日期&#xff1a;9.16 预计截止&#xff1a;9.22 每日更新&#xff0c;学完为止。 学前计划 课…

《粮油与饲料科技》是什么级别的期刊?是正规期刊吗?能评职称吗?

问题解答 问&#xff1a;《粮油与饲料科技》是不是核心期刊&#xff1f; 答&#xff1a;不是&#xff0c;是知网收录的第一批认定 学术期刊。 问&#xff1a;《粮油与饲料科技》级别&#xff1f; 答&#xff1a;省级。主管单位&#xff1a;中文天地出版传媒集团股份有限公司…

漏洞复现_永恒之蓝

1.概述 永恒之蓝&#xff08;EternalBlue&#xff09;是一个影响Windows操作系统的远程代码执行漏洞&#xff0c;编号为CVE-2017-0144&#xff0c;最初由美国国家安全局&#xff08;NSA&#xff09;开发并利用&#xff0c;后来被黑客组织Shadow Brokers泄露。该漏洞存在于SMBv…

Gitee Pipeline 从入门到实战【详细步骤】

文章目录 Gitee Pipeline 简介Gitee Pipeline 实战案例 1 - 前端部署输入源NPM 构建Docker 镜像构建Shell 命令执行案例 2 - 后端部署全局参数输入源Maven 构建Docker 镜像构建Shell 命令执行参考🚀 本文目标:快速了解 Gitee Pipeline,并实现前端及后端打包部署。 Gitee Pi…

【d46】【Java】【力扣】876.链表的中间结点

思路 先获得总体长度&#xff0c; 再得到中间节点 的索引&#xff0c;&#xff0c;这里的索引是从1开始的索引&#xff0c;而不是从0开始的索引(这种理解方式更简单) 排错&#xff1a;另一个思路&#xff1a;将链表都放进list&#xff0c;获得中间的数字&#xff0c;然后遍历…

AfuseKt1.3.6-10110功能强大的安卓网络视频播放器,支持多种在线存储和媒体管理平台!

AfuseKt 是一款功能强大的安卓网络视频播放器&#xff0c;专为满足用户对多样化媒体播放需求而设计。它不仅支持多种流行的在线存储和媒体管理平台&#xff0c;如阿里云盘、Alist、WebDAV和Emby等&#xff0c;还提供了刮削功能和海报墙展示&#xff0c;使得用户能够更加便捷地管…

船舶检测系统源码分享

船舶检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

深度学习|误差逆传播:梯度速解

文章目录 引言链式法则误差逆传播加法的逆传播乘法的逆传播逆传播求梯度 SoftmaxWithLoss 层正向传播逆传播代码实现参考 结语 引言 我们知道训练神经网络模型的核心是以损失函数为基准来调整优化网络参数&#xff0c;使得网络的输出尽可能接近真实标签。在神经网络中&#xf…

网络原理(4)——网络层(IP)、数据链路层

1. IP 协议 基本概念&#xff1a; 主机&#xff1a;配有 IP 地址&#xff0c;但是不进行路由控制的设备 路由器&#xff1a;即配有 IP 地址&#xff0c;又能进行路由控制 节点&#xff1a;主机和路由器的统称 IP 协议报头格式 1) 4 位版本&#xff1a;实际上只有两个取值&…

RabbitMQ 高级特性——发送方确认

文章目录 前言发送方确认confirm 确认模式return 退回模式 常见面试题 前言 前面我们学习了 RabbitMQ 中交换机、队列和消息的持久化&#xff0c;这样能够保证存储在 RabbitMQ Broker 中的交换机和队列中的消息实现持久化&#xff0c;就算 RabbitMQ 服务发生了重启或者是宕机&…

安卓13去掉下拉菜单的Dump SysUI 堆的选项 android13删除Dump SysUI 堆

总纲 android13 rom 开发总纲说明 文章目录 1.前言2.问题分析3.代码分析3.1 位置13.2 位置24.代码修改5.编译6.彩蛋1.前言 客户需要去掉下拉菜单里面的Dump SysUI 堆图标,不让使用这个功能。 2.问题分析 android的下拉菜单在systemui里面,这里我们只需要定位到对应的添加代…

通义灵码AI 程序员正式发布:写代码谁还动手啊

虽然见不到面 但你已深潜我心 前几天&#xff0c;在 2024 年的杭州云栖大会上&#xff0c;随着通义大模型能力的全面提升&#xff0c;阿里云通义灵码这位中国的首位 AI 程序员也迎来重大的升级。 一年前这位 AI 程序员还只能完成基础的编程任务&#xff0c;到现在可以做到几…

2024年华为杯研究生数学建模竞赛D题(时空演化模型+脆性指数 完整文章|可视化)

2024年华为杯研究生数学建模竞赛D题 全文请从 底部名片 处加群获取哦~ 问题重述 题目背景&#xff1a; 地理系统是由自然和人文多要素综合作用形成的复杂巨系统。传统上&#xff0c;地理学家通过宏观结构和定性分析方法描述地理系统的主导特征&#xff0c;如地形分布、气候…

LabVIEW闪退

LabVIEW闪退或无法启动可能由多个原因引起&#xff0c;特别是在使用了一段时间后突然发生的问题。重启电脑后 LabVIEW 和所有 NI 软件都无法打开&#xff0c;甚至在卸载和重装时也没有反应。这种情况通常与系统环境、软件冲突或 NI 软件组件的损坏有关。 1. 检查系统和软件冲突…

使用 Docker 部署 RStudio 的终极教程

一.介绍 在现代数据科学和统计分析领域&#xff0c;RStudio 是一个广受欢迎的集成开发环境&#xff08;IDE&#xff09;&#xff0c;为用户提供了强大的工具来编写、调试和可视化 R 代码。然而&#xff0c;传统的 RStudio 安装可能面临环境配置复杂、版本兼容性等问题。Docker…

CentOS7搭建Hadoop3集群教程

一、集群环境说明 1、用VMware安装3台Centos7虚拟机 2、虚拟机配置&#xff1a;2C&#xff0c;2G内存&#xff0c;50G存储 3、集群架构设计 从表格中&#xff0c;可以看出&#xff0c;Hadoop集群&#xff0c;主要有2个模块服务&#xff0c;一个是HDFS服务&#xff0c;一个是YAR…

不靠学历,不拼年资,怎么才能月入2W?

之前统计局发布了《2023年城镇单位就业人员年平均工资情况》&#xff0c;2023年全国城镇非私营单位和私营单位就业人员年平均工资分别为120698元和68340元。也就是说在去年非私营单位就业人员平均月薪1W&#xff0c;而私营单位就业人员平均月薪只有5.7K左右。 图源&#xff1a;…

视频监控相关笔记

一、QT 之 QTreeWidget 树形控件 Qt编程指南&#xff0c;Qt新手教程&#xff0c;Qt Programming Guide 一个树形结构的节点中的图表文本 、附带数据的添加&#xff1a; QTreeWidgetItem* TourTreeWnd::InsertNode(NetNodeInfo node, QTreeWidgetItem* parent_item) { // …

asp.net core日志与异常处理小结

asp.net core的webApplicationBuilder中自带了一个日志组件,无需手动注册服务就能直接在控制器中构造注入&#xff0c;本文主要介绍了net core日志与异常处理小结&#xff0c;需要的朋友可以参考下 ILogger简单使用 asp.net core的webApplicationBuilder中自带了一个日志组件…

Redis的一些数据类型(一)

&#xff08;一&#xff09;数据类型 我们说redis是key value键值对的方式存储数据&#xff0c;key是字符串&#xff0c;而value是一些数据结构,那今天就来说一下value存储的数据。 我们数据结构包含&#xff0c;String&#xff0c;hash&#xff0c;list&#xff0c;set和zest但…