【图论C++】树的重心——教父POJ 3107(链式前向星的使用)

news2024/11/26 16:32:02

》》》算法竞赛

/**
 * @file            
 * @author          jUicE_g2R(qq:3406291309)————彬(bin-必应)
 *						一个某双流一大学通信与信息专业大二在读	
 * 
 * @brief           一直在竞赛算法学习的路上
 * 
 * @copyright       2023.9
 * @COPYRIGHT			 原创技术笔记:转载需获得博主本人同意,且需标明转载源
 * @language        C++
 * @Version         1.0还在学习中  
 */
  • UpData Log👆 2023.9.26 更新进行中
  • Statement0🥇 一起进步
  • Statement1💯 有些描述是个人理解,可能不够标准,但能达其意

技术提升站点

文章目录

  • 》》》算法竞赛
  • 技术提升站点
  • 21 树上问题
    • 21-0 关于 树 的问题 有哪些?
    • 21-1 树的重心
      • 21-1-1 重心是什么?
      • 21-1-2 重心的性质
      • 21-1-2 重心的查找
  • 教父(poj 3107)

21 树上问题

  • 的一种特例 就是 “没有环”连通图

判断一个 是否是一个 ,需要满足的条件:

  • 1)树根:一棵树可以基于无向图有向图,区别在于树根。

    基于无向图的树(无根树),是没有固定树根的(也就是说树根的个数可能不止为1,或说每个结点都能做为树根)

    基于有向图的树(有根树),有且仅有一个树根

  • 2)父节点与子节点的关系:每个节点有且仅有一个父节点。从根节点遍历,必须由父节点遍历到子节点

  • 3)连通性:从 根 出发可以遍历树上所有(除根节点外)节点,且到这些节点的路径只有一条

有根树 与 有向无环图 DAG 的 区别

有向无环图:不能从某点开始经过数点回到该点

有根树 都是 DAGDAG 不一定是 有根树(如下图:虽然没有构成环,但是4号节点同时拥有两个父节点,不符合有根树的定义)

21-0 关于 树 的问题 有哪些?

直通车:

  • 树的判断:判定 图 是否为 树 的方法是 DFS遍历
  • 树的存储:与 图 的存储方式一致(链式前向星)
  • 树的路径问题(包含了 查找最近公共祖先LCA):点击直通 树的路径问题
  • 树的直径
  • 树的重心(下文将讲解)
  • 多叉树、二叉树
  • 树上前缀和,树上差分

21-1 树的重心

21-1-1 重心是什么?

  • 树的重心 适用在 无根树(一个不含回路的无向图)
  • 树的重心 是 以任意结点 u 为根 计算它最大子树的节点数 n o d e n node_n noden,如果 u节点 n o d e n node_n noden 最少,则 u节点 为 树的重心。

可以一眼看出:4号结点 就是 树的重心,因为这个点能满足 n o d e n node_n noden 是最小的(左子树{4,2,1,3,}:4个,右子树{4,5,6,7}:4个),而其他任意一个节点的子树(例如 2号节点的最大子树{2,4,5,6,7}5个)都是比这个点的最大子树的节点数是大的。

21-1-2 重心的性质

  • 以树的重心为根时,所有子树的大小都不超过整棵树大小的一半。(树上分治会用到
  • 树的重心如果不唯一,则至多有两个,且这两个重心相邻
  • 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么到它们的距离和一样
  • 把两棵树通过一条边相连得到一棵新的树,那么新的树的重心在连接原来两棵树的重心的路径上
  • 在一棵树上添加或删除一个叶子,那么它的重心最多只移动一条边的距离。(往树上增加或减少一个叶子,如果原节点数是奇数,那么重心可能增加一个,原重心仍是重心;如果原节点数是偶数,重心可能减少一个,另一个重心仍是重心

21-1-2 重心的查找

教父(poj 3107)

问题描述

城里有一个黑手党组织。把黑手党的人员关系用一棵树来描述,教父是树的根,每个节点是一个组织成员。为了保密,每人只和他的父节点和他的子节点联系。警察知道哪些人互相来往,但是不知他们的关系。警察想找出谁是教父
警察假设教父是一个聪明人:教父懂得制衡手下的权力,所以他直属的几个小头目,每个人的属下的人数差不多。也就是说,删除根之后,剩下几棵互不连通的子树(连通块),其中最大的连通块应该尽可能小。请帮助警察找到哪些人可能是教父。
输入:第1行输入n,表示组织人数, 2 ≤ n ≤ 50000 2\leq n \leq 50000 2n50000 。组织成员的编号为1~n。下面n-1行中,每行输入两个整数,即有联系的两个人的编号。
输出:输出疑似教父的节点编号,从小到大输出。

Input

6
1 2
2 3
2 5
3 4
3 6

Output

2 3
  • 分析

“删除根之后,剩下几棵互不连通的子树(连通块),其中最大的连通块应该尽可能小”,这句话说明了 教父 就是 这个关系树里的 重心

如何计算以 u节点 为根的子树的结点

u节点 DFS 直到“碰壁”后,将栈里的数据依次弹出,弹出一个结点数加1。

那么这样的话,可以对删除根之后,剩下几棵互不连通的子树(连通块) 进行单独的DFS,对整棵树逐一删除节点,重复上述步骤,就能得到每个结点的最大连同块。

如何优化?

上面提出的方案是 使用 暴力法 解决,其实无需如此,可以依照线段树的思维,对 同父节点的子节点 进行合并,得到父节点的子树的节点数,这样一次DFS就可以解决问题。

如上图,假如删除 结点1,得到3个连通块(含结点1的邻居:节点3、含结点1的邻居:节点0、含结点1的邻居:节点4)

对任意点做一次 DFS,特殊点,以 结点2为根节点 做DFS:

从2向0方向 一直DFS,直到遍历到节点10,停止遍历,栈开始弹出数据。,当弹出结点10时,记录 结点10 的度(即子树的结点数) D e g r e e [ 10 ] = 1 Degree[10]=1 Degree[10]=1,同理 D e g r e e [ 9 ] = 1 Degree[9]=1 Degree[9]=1;当弹出4时, D e g r e e [ 4 ] = D e g r e e [ 9 ] + D e g r e e [ 10 ] + 1 = 3 Degree[4]=Degree[9]+Degree[10]+1=3 Degree[4]=Degree[9]+Degree[10]+1=3,同理算出 D e g r e e [ 3 ] = D e g r e e [ 7 ] + D e g r e e [ 8 ] + 1 = 3 Degree[3]=Degree[7]+Degree[8]+1=3 Degree[3]=Degree[7]+Degree[8]+1=3;在弹出1时, D e g r e e [ 1 ] = D e g r e e [ 3 ] + D e g r e e [ 4 ] + 1 = 7 Degree[1]=Degree[3]+Degree[4]+1=7 Degree[1]=Degree[3]+Degree[4]+1=7;删除1后, D e g r e e [ 0 ] = n − D e g r e e [ 1 ] Degree[0]=n-Degree[1] Degree[0]=nDegree[1]

存储:链式前向星

链式前向星领接矩阵(二维数组)在空间上优化了很多

点击直通 链式前向星(图(树)的存储)

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=5e5+5;
vector<int> head(N,-1);
struct Edge{
    int to,next;
    Edge():to(-1), next(-1){}				        //初始化为无邻居节点
} edge[N<<1];
vector<int> Degree(N,1);                            //初始化每个节点的度(子树的结点数)为1
int edge_n=0;                                       //记录边数
int GodFather_n=0;                                  //记录可能得教父个数
int n;                                              //人有n个,关系有n-1条
int MAX_Degree=1e9;
vector<int> ans(N,0);
void Add_Edge(int u, int v){
    edge[edge_n].to=v;
    edge[edge_n].next=head[u];                     //记录 上一个邻居节点 的 存储编号
    head[u]=edge_n++;                              //当前 邻居节点 的 存储编号,以便下一个邻居节点的访问
}
void DFS(int u=1, int father=0){
    /*计算 cur结点 的 最大连通块的结点数*/
    int temp=0;
    for(int i=head[u]; ~i; i=edge[i].next){         //遍历cur节点的邻居节点[~i相当于i=-1]
        int v=edge[i].to;                           //v 是 u 的子节点
        if(v==father)     continue;
        DFS(v,u);                                   //DFS子树
        Degree[u]+=Degree[v];                       //更新父节点的度
        temp=max(temp, Degree[v]);                  //记录cur结点的 最大子树 的 结点数
    }
    temp=max(temp, n-Degree[u]);                    //temp是cur最大连通块的节点数

    /*查找 结点数 最小的 最大连通块*/
    if(temp<MAX_Degree){                            //满足条件的话,则temp是 疑似教父 的最大连通块的结点数
        MAX_Degree=temp;                            //更新 最小的 最大连通块
        GodFather_n=0;                              //找到新的最小,将它放在第一个
        ans[++GodFather_n]=u;
    }
    else if(temp==MAX_Degree)
        ans[++GodFather_n]=u;
}

int main(int* argc, void* argv[]){
    cin>>n;
    for(int i=1; i<n;i++){
        int u,v;    cin>> u >> v;
        Add_Edge(u,v);  Add_Edge(v,u);              //无向 记录 双向有向
    }
    DFS();
    sort(ans.data()+1, ans.data()+1+GodFather_n);   //升序排列
    for(int i=1; i<=GodFather_n; i++)
        cout<<ans[i]<<" ";
    return 0;
}

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

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

相关文章

$nextTick解决echarts宽度固定为100%的问题

问题描述:vue+element项目中使用到了tab切换选项卡,其中有一个tab下的内容是echarts,出现了echarts宽度缩减为100px无法继承100%属性。 问题: echarts渲染时tab选项卡display为none,所以width:100%没有可继承项,被echarts自带方法切割成100px。 我他喵的解决这个问题还是…

给 shell 自定义快捷键

shell 快捷键原理 本质上对于 shell 来说只有输入输出&#xff0c;它不会监听你系统快捷键的&#xff0c;监听快捷键其实是终端模拟器的责任&#xff0c;他会将你输入的快捷键转换成字符串序列。当我们使用了类似 ctrl -> 这样的快捷键&#xff0c;shell 会根据你输入的字…

QT的ui设计中改变样式表的用法

在QT的ui设计中,我们右键会弹出一个改变样式表的选项,很多人不知道这个是干什么的。 首先我们来看下具体的界面 首先我们说一下这个功能具体是干嘛的, 我们在设置很多控件在界面上之后,常常都是使用系统默认的样式,但是当有些时候为了美化界面我们需要对一些控件进行美化…

进阶JS-内置构造函数

基本数据类型&#xff1a;string、number、boolean、undefined、null 引用类型:对象 其实字符串、数值、布尔等基本类型也都有专门的构造函数&#xff0c;这些我们称为包装类型。 JS中几乎所有的数据都可以基于构成函数创建。 const str andy//其实是const strnew String(a…

【EI会议征稿】第三届机械、建模与材料工程国际学术会议(I3ME 2023)

第三届机械、建模与材料工程国际学术会议&#xff08;I3ME 2023&#xff09; 2023 3rd International Conference on Mechanical, Modeling and Materials Engineering 第三届机械、建模与材料工程国际学术会议&#xff08;I3ME 2023&#xff09;将于2023年12月1-3日在中国长春…

一套成熟的Spring Cloud智慧工地平台源码,自主版权,开箱即用

智慧工地云平台源码 APP端PC端数据大屏端全套源码 自主版权&#xff0c;开箱即可项目使用 智慧工地利用移动互联、物联网、云计算、大数据等新一代信息技术&#xff0c;彻底改变传统施工现场各参建方的交互方式、工作方式和管理模式&#xff0c;为建设集团、施工企业、监理单位…

第二证券:券商近期关注点浮现 扎堆调研19只个股 上调旅游股评级

19只个股 被券商扎堆调研 东方财富Choice数据显现&#xff0c;9月以来券商保持高强度的调研节奏&#xff0c;19只个股获得超25家券商扎堆调研&#xff0c;首要会合在半导体、医药生物、新能源、机械设备等范畴。人气最高的股票分别是埃斯顿、周大生、南网科技、卫星化学、宁波…

11.1Spring基础(核心概念,创建和使用,简单读取)

一.Spring概念: 1.Spring就是包含了众多工具方法的IoC容器. 2.IoC容器:控制反转,指的是对象的生命周期,将对象的生命周期(什么时候创建,销毁)交给Spring进行管理. 在传统开发中,如果A类依赖B类,会在A类中创建B类的实例,如果B类增加一个属性,那么使用B类的构造方法需要修改代码…

Java基于SpringBoot的原创歌曲分享平台

文章目录 1 简介2 技术栈3 需求分析4 平台设计主要功能5 平台实现5.1平台功能模块 5.2后台功能模块52.1管理员功能模块5.2.2用户功能模块 源码咨询 1 简介 原创歌曲分享平台&#xff0c;为了随时随地查看原创歌曲分享信息提供了便捷的方法&#xff0c;更重要的是大大的简化了管…

外卖霸王餐平台究竟是如何运作的?以及盈利点到底在哪里?

外卖霸王餐 1、业务简介。业务模式是消费者以5-10元吃到原价15-25元的外卖&#xff0c;底层逻辑是帮外卖商家做推广&#xff0c;解决新店基础销量、老店增加单量、品牌打万单店的需求。 因为外卖店的平均生命周期只有6个月&#xff0c;不断有新店愿意送霸王餐。部分老店也愿…

指南:通过 NFTScan API 获取钱包地址的 NFT Statistics 全量数据

获取钱包地址的全量 NFT 及统计分析数据对于开发者和投资者来说都是十分重要的。具体来说&#xff1a;对开发者而言&#xff0c;获取每个钱包的完整资产数据&#xff0c;并进行统计分析&#xff0c;是构建钱包管理工具、资产分析应用的基础&#xff0c;这些应用都需要全面且精确…

安装typescript之后提示不是内部命令

解决方案&#xff1a; 1、删除C:\Users\用户\下的.npmrc文件 2、在命令行输入npm cache clean --force 以上提示表示执行成功 3、重新安装typescript npm install -g typescript tsc

算法-堆/多路归并-查找和最小的 K 对数字

算法-堆/多路归并-查找和最小的 K 对数字 1 题目概述 1.1 题目出处 https://leetcode.cn/problems/find-k-pairs-with-smallest-sums/description/?envTypestudy-plan-v2&envIdtop-interview-150 1.2 题目描述 2 优先级队列构建大顶堆 2.1 思路 将两个数字的和放入大…

同一台电脑下的wireshark的http抓包查看使用的接口

开发过程中写软件开发设计时需要写调用的接口&#xff0c; 可以使用抓包软件 操作一遍&#xff0c;看抓包记录 然后看自己需要的接口调用情况 同一台电脑用这个 设置需要的抓包协议 在后台搜索关键词也可以看到用了哪些接口 Json查看器也可以查看接口信息

Vue+element开发Simple Admin后端管理系统页面

最近看到各种admin&#xff0c;头大&#xff0c;内容太多&#xff0c;根本不知道怎么改。所以制作了这个项目&#xff0c;只包含框架、和开发中最常用的表格和表单&#xff0c;不用自己从头搭建架构&#xff0c;同时也容易上手二次开发。可以轻松从其他开源项目整合到本项目。项…

避障技术再提升,扫地机器人避障不止于精准

扫地机器人好用与否&#xff0c;避障表现首当其冲&#xff0c;那么评判避障好坏的标准又是什么&#xff1f; 有效避障仅是第一步 时至今日&#xff0c;可以说仍有相当一部分人对于扫地机器人的印象停留在人工“智障”上&#xff0c;由于早期的产品基本不具备避障能力&#xf…

ArcGIS 10.7软件安装包下载及安装教程!

【软件名称】&#xff1a;ArcGIS 10.7 【安装环境】&#xff1a;Windows 【下载链接 】&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1IwsPubYWGHd9ztmn45QLJA 提取码&#xff1a;1oeq 复制这段内容后打开百度网盘手机App&#xff0c;操作更方便哦 软件简介 ArcGIS…

ubuntu16编译linux源码内核

一、环境准备 1.1、安装虚拟机ubuntu16 编译内核大概需要20G的磁盘空间&#xff0c;所以硬盘大小尽量大于40G网络适配使用桥接 1.1.1、查看当前内核版本 uname -r1.2、安装samba服务 Samba 是一款数据共享的软件&#xff0c;可用于 Ubuntu 与 Windows 之间共享源代码&#…

Flink容错机制

容错机制 在Flink中&#xff0c;有一套完整的容错机制来保证故障后的恢复&#xff0c;其中最重要的就是检查点。 检查点的保存 1&#xff09;周期性的触发保存 “随时存档”确实恢复起来方便&#xff0c;可是需要我们不停地做存档操作。如果每处理一条数据就进行检查点的保存…