树的直径、树的重心与树的点分治
转载自:树的直径、树的重心与树的点分治
树的直径
1.定义:
树的直径(Diameter)是指树上的最长简单路。
2.求解思路:
两遍搜索 (BFS or DFS)
任选一点w为起点,对树进行搜索,找出离w最远的点u。
以u为起点,再进行搜索,找出离u最远的点v。
则u到v的路径长度即为树的直径。
树的重心
1.定义:
找到一个点,其所有的子树中最大的子树节点数最少,那么这个点就是这棵树的重心,删去重心后,生成的多棵树尽可能平衡。
2.求解思路:
定义son[ i ]:以节点 i 为根节点的子树节点的总个数;
对于节点 i,定义 cnt[ i ]为其所有子树中最大的子树节点个数;
令 x = max{ son[ j ] }+1( j 为节点 i 的所有儿子节点),y = n-son[ i ]-1;
那么,cnt[ i ]=max{x,y}
使cnt[ i ]最小的 i 便是此树的重心;
代码:
1 //初始cnt=INF,k=0 2 void Dfs(int u,int f,int &cnt,int &k) 3 { 4 son[u]=0; 5 int temp=0; 6 for(int i=head[u];~i;i=G[i].next) 7 { 8 int v=G[i].to; 9 if(v == f) 10 continue; 11 12 Dfs(v,u,cnt,k); 13 14 son[u] += son[v]+1; 15 temp=max(temp,son[v]+1);//以u的儿子节点为根节点的子树的最大节点个数 16 } 17 temp=max(temp,n-son[u]-1); 18 if(temp < cnt) 19 { 20 k=0; 21 a[k++]=u;//存储此树的所有重心 22 cnt=temp;//存储最大子树的最小节点个数 23 } 24 else if(temp == cnt) 25 a[k++]=u; 26 }
相关习题: