• 【树】树的直径和重心


    目录

    一.树的直径

    (1)定义

    (2)思路

    (3)例题 

    (4)std(第一小问)

    二.树的重心

    (1)介绍

    (2)求重心

    (3)例题

    (4)AC


    一.树的直径

    (1)定义

    树的直径是指树中最长的一条路径的长度,这条路径连接树中的两个节点,使得它们之间的距离最远。

    (2)思路

    (3)例题 

    P3304 [SDOI2013] 直径 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

    (4)std(第一小问)

    1. #include
    2. using namespace std;
    3. const int maxn=2e5+5;
    4. int n;
    5. struct Edge{
    6. int u,v,w,next;
    7. }edge[maxn<<1];
    8. int head[maxn],cnt;
    9. void add(int u,int v,int w){
    10. edge[++cnt]=(Edge){u,v,w,head[u]}; head[u]=cnt;
    11. }
    12. int root,lon;
    13. void dfs(int u,int fa,int p){
    14. if(p>lon){
    15. root=u;
    16. lon=p;
    17. }
    18. for(int i=head[u];i;i=edge[i].next){
    19. int v=edge[i].v;
    20. if(v==fa) continue;
    21. dfs(v,u,p+edge[i].w);
    22. }
    23. }
    24. int main(){
    25. scanf("%d",&n);
    26. for(int i=1,u,v,w;i
    27. scanf("%d%d%d",&u,&v,&w);
    28. add(u,v,w); add(v,u,w);
    29. }
    30. dfs(1,0,0);
    31. lon=0;
    32. dfs(root,0,0);
    33. printf("%d",lon);
    34. return 0;
    35. }

    二.树的重心

    (1)介绍

     树的重心是指树中的一个节点,通过删除该节点后,将树分成多个子树,使得每个子树的节点数都不超过整棵树节点数的一半。换句话说,树的重心是树的一种结构特征,它能够将树尽可能平衡地分割成多个相对均匀的部分。

    说人话就是重心在树所有节点中,它的最大子树的节点最小

    寻找树的重心通常可以通过以下步骤来实现:

    1. 选择任意一个节点作为树的根节点。
    2. 对树进行深度优先搜索(DFS)或广度优先搜索(BFS),计算每个节点的子树大小(包括自身节点)。
    3. 对于每个节点,计算删除该节点后,各个子树的大小(即除去该节点后,以其邻居节点为根的子树大小)。
    4. 找到一个节点,使得删除该节点后,各个子树的大小都不超过整棵树节点数的一半。这个节点就是树的重心。

    (2)求重心

    1. #include
    2. #define maxn 10005
    3. using namespace std;
    4. int n;
    5. int size[maxn],f[maxn]; //子树总大小 && 最大子树
    6. struct Edge{
    7. int u,v,next;
    8. }edge[maxn<<1];
    9. int head[maxn],cnt;
    10. void add(int u,int v){
    11. edge[++cnt]=(Edge){u,v,head[u]}; head[u]=cnt;
    12. }
    13. int root,MAX=0x7fffffff;
    14. void dfs(int u,int fa){
    15. size[u]=1;
    16. for(int i=head[u];i;i=edge[i].next){
    17. int v=edge[i].v;
    18. if(v!=fa){
    19. dfs(v,u);
    20. size[u]+=size[v];
    21. f[u]=max(f[u],size[v]);
    22. }
    23. }
    24. f[u]=max(f[u],n-size[u]);
    25. if(f[u]
    26. MAX=f[u];
    27. root=u;
    28. }
    29. }
    30. int main(){
    31. scanf("%d",&n);
    32. int x,y;
    33. for(int i=1;i
    34. scanf("%d%d",&x,&y);
    35. add(x,y); add(y,x);
    36. }
    37. dfs(1,0);
    38. printf("%d",root);
    39. return 0;
    40. }

    (3)例题

    P1395 会议 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

    (4)AC

    1. #include
    2. #define maxn 50005
    3. using namespace std;
    4. int n;
    5. int size[maxn],f[maxn]; //子树总大小 && 最大子树
    6. struct Edge{
    7. int u,v,w,next;
    8. }edge[maxn<<1];
    9. int head[maxn],cnt;
    10. void add(int u,int v,int w){
    11. edge[++cnt]=(Edge){u,v,w,head[u]}; head[u]=cnt;
    12. }
    13. int root,MAX=0x7fffffff;
    14. void dfs(int u,int fa){
    15. size[u]=1;
    16. for(int i=head[u];i;i=edge[i].next){
    17. int v=edge[i].v;
    18. if(v!=fa){
    19. dfs(v,u);
    20. size[u]+=size[v];
    21. f[u]=max(f[u],size[v]);
    22. }
    23. }
    24. f[u]=max(f[u],n-size[u]);
    25. if(f[u]
    26. MAX=f[u];
    27. root=u;
    28. }
    29. }
    30. struct node{
    31. int u,w;
    32. bool operator < (const node &x) const{
    33. return x.w
    34. }
    35. };
    36. int dis[maxn],vis[maxn];
    37. void Djkstra(){
    38. for(int i=1;i<=n;i++) dis[i]=0x7fffffff;
    39. dis[root]=0;
    40. priority_queue q;
    41. q.push((node){root,0});
    42. while(!q.empty()){
    43. node temp=q.top(); q.pop();
    44. int u=temp.u;
    45. if(vis[u]) continue;
    46. vis[u]=1;
    47. for(int i=head[u];i;i=edge[i].next){
    48. int v=edge[i].v,w=edge[i].w;
    49. if(dis[u]+w
    50. dis[v]=dis[u]+w;
    51. q.push((node){v,dis[v]});
    52. }
    53. }
    54. }
    55. }
    56. int main(){
    57. scanf("%d",&n);
    58. int x,y;
    59. for(int i=1;i
    60. scanf("%d%d",&x,&y);
    61. add(x,y,1); add(y,x,1);
    62. }
    63. dfs(1,0);
    64. printf("%d ",root);
    65. Djkstra();
    66. long long ans=0;
    67. for(int i=1;i<=n;i++) ans+=dis[i];
    68. printf("%lld",ans);
    69. return 0;
    70. }

  • 相关阅读:
    JAVA计算机毕业设计手办销售系统源码+系统+mysql数据库+lw文档
    Dubbo:服务调用
    热烈祝贺埃文科技代码特工队斩获2023黄河鲲鹏开发者大赛河南赛区创新赛道二等奖
    Spring - Spring Cloud Gateway网关实战及原理解析
    Flutter实现地图上汇聚到一点的效果。
    前端怎么debugger排查线上问题
    Windows线程简介
    【学习笔记-李宏毅】GAN(生成对抗网络)全系列(一)
    QML语法基础三
    探索Linux中的fdisk命令:磁盘分区管理的利器
  • 原文地址:https://blog.csdn.net/qq_49705495/article/details/133584127