Balancing Act (树形dp+树的重心)

本文介绍了一种通过深度优先搜索(DFS)算法来寻找一棵树的重心的方法,并提供了一个具体的实现案例。文章详细解释了树的重心概念及其计算过程,旨在帮助读者理解如何找到树中具有最小平衡度的节点。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Consider a tree T with N (1 <= N <= 20,000) nodes numbered 1...N. Deleting any node from the tree yields a forest: a collection of one or more trees. Define the balance of a node to be the size of the largest tree in the forest T created by deleting that node from T.
For example, consider the tree:


Deleting node 4 yields two trees whose member nodes are {5} and {1,2,3,6,7}. The larger of these two trees has five nodes, thus the balance of node 4 is five. Deleting node 1 yields a forest of three trees of equal size: {2,6}, {3,7}, and {4,5}. Each of these trees has two nodes, so the balance of node 1 is two.

For each input tree, calculate the node that has the minimum balance. If multiple nodes have equal balance, output the one with the lowest number.
Input
The first line of input contains a single integer t (1 <= t <= 20), the number of test cases. The first line of each test case contains an integer N (1 <= N <= 20,000), the number of congruence. The next N-1 lines each contains two space-separated node numbers that are the endpoints of an edge in the tree. No edge will be listed twice, and all edges will be listed.
Output
For each test case, print a line containing two integers, the number of the node with minimum balance and the balance of that node.
Sample Input
1
7
2 6
1 2
1 4
4 5
3 7
3 1
Sample Output
1 2


题目大概:

给出一棵树,找出它的重心是哪个节点,它的最小额度是多少(即最大子树的结点数)。

思路:

首先要知道重心定义,

树的重心是,与重心相连的所有子树中,结点数最多的子树   是所有节点的最多子树中最少的。

然后就dfs遍求出最小的额度。然后从1开始判断就可以了。


代码:


#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;

int n;
int dp[20005];
int d[20005];
int head[20005];
int minshu,no;
int ans;
struct shu
{
    int v;
    int next;
}tr[40010];

void add(int q,int w)
{
    tr[ans].v=w;
    tr[ans].next=head[q];
    head[q]=ans++;

}

void dfs(int x,int pa)
{
    d[x]=1;
    int maxshu=-20005;
    for(int i=head[x];i!=-1;i=tr[i].next)
    {
        int son=tr[i].v;
        if(son!=pa)
        {
            dfs(son,x);
            d[x]+=d[son];
            maxshu=max(maxshu,d[son]);
        }
    }
    dp[x]=max(maxshu,n-d[x]);
    if(minshu>dp[x])
    {
        minshu=dp[x];

    }

}

int main()
{
    int t;
    scanf("%d",&t);
   while(t--)
   {
       memset(dp,0,sizeof(dp));
       memset(d,0,sizeof(d));
       memset(head,-1,sizeof(head));
       ans=0;
       scanf("%d",&n);
       for(int i=1;i<n;i++)
       {
           int q,w;
            scanf("%d%d",&q,&w);
            add(q,w);
            add(w,q);

       }
       minshu=20005;
       no=0;
       dfs(1,0);
       for(int i=n;i>=1;i--)
       {
           if(minshu==dp[i])
           {
               no=i;
           }
       }
       printf("%d %d\n",no,minshu);
   }
    return 0;
}






### 不同类型树结构的特点与区别 #### 二叉树特点 一棵空树,或者是具有特定性质的二叉树:如果左子树非空,则左子树上所有结点的值均小于根结点的值;若右子树非空,则右子树上所有结点的值均大于根结点的值。而且,左、右子树也各自构成二叉排序树[^2]。 #### 红黑树特性 红黑树是一种自平衡二叉搜索树,在保持基本二叉搜索特性的基础上引入了颜色标记(红色或黑色),并通过一系列严格规定来确保任何路径从根到叶节点所经过的黑色节点数目相同,以此维持近似平衡状态,从而保障操作时间复杂度接近对数级O(log N)[^1]。 #### B树特征 作为一种多路查找树,B树通过允许每个内部节点拥有多个键值以及两个以上的孩子节点实现了更高效的磁盘读写优化。具体而言,B树能够保证任意一条由根至叶子节点路径上的节点数量大致相等,并且支持动态调整以维护这种平衡性,进而使各种操作的时间复杂度稳定在O(log N)范围内[^4]。 #### B+树特色 作为B树的一种变体,B+树不仅继承了前者的优势,还进一步改进了范围查询性能——所有的关键字都存储在叶子层中形成有序链表连接起来,这使得区间扫描变得非常高效。此外,由于非叶子节点仅保存用于索引引导的信息而不含实际数据项,因此可以容纳更多指针指向其他下一层节点,提高了扇出率并减少了访问次数。 ```python class Node: def __init__(self, value=None): self.value = value self.left_child = None self.right_child = None def insert(root, key): if not root: return Node(key) elif key < root.value: root.left_child = insert(root.left_child, key) else: root.right_child = insert(root.right_child, key) # Code continues with balancing logic... ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值