因为树不会存在环,所以在dfs树的时候不必vis,只需不走回头路v!=fa即可
一.树的高度与深度
void dfs(int u,int fa){
dep[u]=dep[fa]+1;//u比 fa深 1
size[u]=1;//u节点自己算一个
high[u]=1;
for(int i=vex[u];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);
size[u]+=size[v];//父节点的节点数等于所有子树的节点数之和
high[u]=high[v]+1;//只有叶子节点 high会不被修改,始终如 1
}
}
二.树的直径
定义:树中相邻最远的两个点的距离,即maxdis(s,t)
算法:从任意出发,求出最远点s,再从s出发,求出最远点t
则:树的直径 = dis(s,t)
void dfs(int u,int fa){
for(int i=vex[u];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
dis[v]=dis[u]+e[i].c;
dfs(v,u);
}
}
int findmaxdis(){
dfs(1);
int s=0,t,maxdis=-1e9;
for(int i=1;i<=n;i++){
if(dis[i]>maxdis){
maxdis=dis[i];
s=i;
}
dis[i]=0;
}
dfs(s);
maxdis=-1e9;
for(int i=1;i<=n;i++){
if(dis[i]>maxdis){
maxdis=dis[i];
t=i;
}
dis[i]=0;
}
return maxdis;
//即树的直径为s-t
}
三.树的重心(质心)
定义:对于一棵n个节点的树,找到一个点,使得删除该点后的最大连通块节点数最小
性质1:删除重心后所得的所有子树,节点数不超过原树的1/2
性质2:一棵树最多有两个重心
性质3:树中所有点到重心的距离之和最小,如果有两个重心,那两个距离之和相等
性质4:树删除或添加一个叶子节点,重心最多只移动一条边
性质5:两个树通过一条边合并,新的重心在原树两个重心的路径上
根据性质1,写出相应的求重心算法
void dfs(int u,int fa){
size[u]=1;
int maxnode=0;
for(int i=vex[u];i;i=e[i].next){
int v=e[i].v;
if(v==fa)continue;
dfs(v,u);
size[u]+=size[v];
maxnode=max(maxnode,size[v]);
}
maxnode=max(maxnode,n-size[u]);
//maxnode就是最大的子树节点个数
if(maxnode*2<=n)zon[u]=1;
}