数据结构——树
一些基础知识:
1.二叉搜索树:又名有序二叉树,结点元素按固定次序排布,使得我们可以在进行查找等操作时使用二分搜索提高效率。
它最明显的特征是: 父结点值大于左子树任意结点值,小于右子树任意结点值。
2.树的重心也叫树的质心。对于一棵树n个节点的树,找到一个点,使得把树变成以该点为根。
重心的三个的性质:
- 树中所有点到某个点的距离和中,到重心的距离和是最小的;如果有两个重心,那么他们的距离和一样。
- 把两个树通过一条边相连得到一个新的树,那么新的树的重心在连接原来两个树的重心的路径上。
- 把一个树添加或删除一个叶子,那么它的重心最多只移动一条边的距离。
树的重心模板代码:
//***************树的重心
#include<bits/stdc++.h>
#define mp make_pair
#define se second
#define fi first
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, int> pli;
typedef pair<ll, ll> pll;
typedef long double ld;
const int N=2e4+10;
const int maxn=20010;
const int INF=0x3f3f3f3f;
const double eps=0.0000001;
const ll mod=998244353;
int n,m,x,y,z,k,cnt,t,len,q;
vector<int>G[maxn];
int son[maxn];//然后设son[i]表示以i为根的子树的节点个数(不包括根)
int ans,balance;//ans重心 balance平衡最大子树的最小节点
void ReadTree()
{
//输入n-1条边
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
int s,e;
scanf("%d%d",&s,&e);
G[s].push_back(e);
G[e].push_back(s);
}
}
void dfs(int u,int fa)
{
//O(n)搜一遍即可
son[u]=0;
int d=G[u].size();
int pre_balance=0;
for(int i=0;i<d;i++)
{
int v=G[u][i];
if(v!=fa)
{
dfs(v,u);
son[u]+=son[v]+1;//合并子树
pre_balance=max(pre_balance,son[v]+1);
//如果以u为重心 算平衡子叶
}
}
//如果以u的父亲为重心 算平衡子叶
pre_balance=max(pre_balance,n-son[u]-1);
//printf("删除节点: %d 最大子树节点数%d\n",v,pre_balance);
if(pre_balance<balance||(pre