题意:

给你一个由n个节点n-1条边构成的一棵树,你需要输出树的重心是那个节点,以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的

题解:

树的重心定义:
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,
生成的多棵树尽可能平衡。

洛谷中P5666树的重心  对树的重心还有这样一种描述:

一个大小为 n 的树由 nn 个结点与 n−1 条无向边构成,且满足任意两个结点间有且仅有一条简单路径。在树中删去一个结点及与它关联的边,树将分裂为若干个子树;而在树中删去一条边(保留关联结点,下同),树将分裂为恰好两个子树。

对于一个大小为 n 的树与任意一个树中结点 c,称 c 是该树的重心当且仅当在树中删去 c 及与它关联的边后,分裂出的所有子树的大小均不超过 floor(n/2)(其中 floor⌊x⌋ 是向下取整函数)。对于包含至少一个结点的树,它的重心只可能有 1 或 2 个。

树的重心的性质:
1.树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
2.把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。
3.把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。

回归原题:

这道题我们可以随便找一个节点当作树根,然后dfs处理出来每一个节点的子节点的数量sonnum和每一个节点的子树中最大那颗子树的大小sonmax

树的定义中说过:“找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心

那么对于一个节点x,它所有子树中最大子树节点数就是:max(sonmax[i],n-sonnum[i])

sonmax[i]:表示的是x节点的子树中最大那颗子树的大小

n-sonnum[i]:表示的是不是x的子节点的剩下所有点构成的那颗树的大小

代码:

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
#define mem(a) memset(a,0,sizeof(a))
#define mem_(a) memset(a,-1,sizeof(a))
const int maxn=2e4+10;
const int INF=0x3f3f3f3f;
//链式前向星
struct node
{
int to,w,next;
}e[maxn*2]; //这个是有多少边数组就开多少
int head[maxn],cnt,sonnum[maxn],sonmax[maxn];
void add_edge(int x,int y,int z)
{
e[cnt].to=y;
e[cnt].w=z;
e[cnt].next=head[x];
head[x]=cnt++;
}
void dfs(int now,int pre)
{
sonnum[now]=1;
sonmax[now]=0;
for(int i=head[now];~i;i=e[i].next)
{
int to=e[i].to;
if(to==pre) continue;
dfs(to,now);
sonnum[now]+=sonnum[to];
sonmax[now]=max(sonmax[now],sonnum[to]);
}
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
cnt=1;
mem_(head);
for(int i=1;i<n;++i)
{
int x,y;
scanf("%d%d",&x,&y);
add_edge(x,y,0);
add_edge(y,x,0);
}
dfs(1,0);
int minn=INF,pos;
for(int i=1;i<=n;++i)
{
//根据树的重心的定义,我们发现判断一个点是不是重心 只要把这个点去掉
//看它剩下的子树结点的个数的最大值是不是最小就ok了
//子树有两种:一个是往下的即sonMax[i],另一个是往上的 即n - sonNum[i]
//printf("%d %d***********\n",sonmax[i],n-sonnum[i]);
if(minn>max(sonmax[i],n-sonnum[i]))
{ minn=max(sonmax[i],n-sonnum[i]);
pos=i;
}
}
printf("%d %d\n",pos,minn);
}
return 0;
}

POJ 1655 Balancing Act ( 树的重心板子题,链式前向星建图)的更多相关文章

  1. POJ 1655 Balancing Act 树的重心

    Balancing Act   Description Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. ...

  2. POJ 1655 - Balancing Act 树型DP

    这题和POJ 3107 - Godfather异曲同工...http://blog.csdn.net/kk303/article/details/9387251 Program: #include&l ...

  3. # [Poj 3107] Godfather 链式前向星+树的重心

    [Poj 3107] Godfather 链式前向星+树的重心 题意 http://poj.org/problem?id=3107 给定一棵树,找到所有重心,升序输出,n<=50000. 链式前 ...

  4. 链式前向星版DIjistra POJ 2387

    链式前向星 在做图论题的时候,偶然碰到了一个数据量很大的题目,用vector的邻接表直接超时,上网查了一下发现这道题数据很大,vector可定会超的,不会指针链表的我找到了链式前向星这个好东西,接下来 ...

  5. POJ.1655 Balancing Act POJ.3107 Godfather(树的重心)

    关于树的重心:百度百科 有关博客:http://blog.csdn.net/acdreamers/article/details/16905653 1.Balancing Act To POJ.165 ...

  6. poj 1655 Balancing Act 求树的重心【树形dp】

    poj 1655 Balancing Act 题意:求树的重心且编号数最小 一棵树的重心是指一个结点u,去掉它后剩下的子树结点数最少. (图片来源: PatrickZhou 感谢博主) 看上面的图就好 ...

  7. POJ 1655 Balancing Act【树的重心】

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14251   Accepted: 6027 De ...

  8. POJ 1655.Balancing Act 树形dp 树的重心

    Balancing Act Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 14550   Accepted: 6173 De ...

  9. poj 1655 Balancing Act(找树的重心)

    Balancing Act POJ - 1655 题意:给定一棵树,求树的重心的编号以及重心删除后得到的最大子树的节点个数size,如果size相同就选取编号最小的. /* 找树的重心可以用树形dp或 ...

随机推荐

  1. 【Flutter】容器类组件之变换

    前言 Transform可以在其子组件绘制时对其应用一些矩阵变换来实现一些特效. 接口描述 const Transform({ Key key, @required this.transform, t ...

  2. 基于JavaFX实现的音乐播放器

    前言 这个是本科四年的毕业设计,我个人自命题的一个音乐播放器的设计与实现,其实也存在一些功能还没完全开发完成,但粗略的答辩也就过去了,还让我拿了个优秀,好开心.界面UI是参考网易云UWP版本的,即使这 ...

  3. Python使用Protobuf&&如何赋值&&如何正反序列化

    前言 使用protobuf主要是两个步骤,序列化和反序列化. 关于Proto有哪些数据类型,然后如何编写,此处就不赘述了,百度一下有很多. 此文主要是总结,python使用protobuf的过程,如何 ...

  4. Java JDK8下载 (jdk-8u251-windows-x64和jdk-8u271-linux-x64.tar)

    jdk-8u251-windows-x64 和 jdk-8u271-linux-x64.tar 链接:https://pan.baidu.com/s/1gci6aSIFhEhjY8F48qH39Q 提 ...

  5. 【Oracle】查看哪些用户被授予了DBA权限

    查看哪些用户被授予了DBA权限 select * from dba_role_privs where granted_role='DBA'; 回收权限: revoke dba from xxx;

  6. 以事实驳斥:改进你的c#代码的5个技巧(四)

    测试使用的环境:vs2019+.net core3.1 原文地址:https://www.cnblogs.com/hhhnicvscs/p/14296715.html 反驳第一条:如何检查代码中的空字 ...

  7. Flink源码剖析:Jar包任务提交流程

    Flink基于用户程序生成JobGraph,提交到集群进行分布式部署运行.本篇从源码角度讲解一下Flink Jar包是如何被提交到集群的.(本文源码基于Flink 1.11.3) 1 Flink ru ...

  8. LeetCode559.N 叉树的最大深度

    题目 法一.层序遍历 1 class Solution { 2 public: 3 int maxDepth(Node* root) { 4 if(root== NULL) return 0; 5 q ...

  9. MySQL之谓词下推

    MySQL之谓词下推 什么是谓词 在SQL中,谓词就是返回boolean值即true或者false的函数,或是隐式转换为boolean的函数.SQL中的谓词主要有 LKIE.BETWEEN.IS NU ...

  10. https://www.cnblogs.com/AloneSword/p/3209653.html

    proc/sys/net/ipv4/下各项的意义 - 孤剑 - 博客园 https://www.cnblogs.com/AloneSword/p/3209653.html