当前位置 博文首页 > Plus Ultra!:图论 —— 树的直径 及 其两种求法
树的直径,即 树上最远的两点的距离(即 树上最大距离),若树的边权全为 1 1 1,则树的直径即是 树上的最长链。
通常有两种树的直径的求法,时间复杂度均为 O ( n ) O(n) O(n)
改方法只需遍历一次,即可求得树的直径大小,但无法求得直径的具体路径。
选取任意结点为根遍历树,设 d [ i ] : d[i]: d[i]:表示结点 i i i为根的子树结点最远距离。
则有:
最后直径即为 根结点 的 两个最远距离之和
int d[maxn],len=0;
void DP(int u,int pre)
{
d[u]=0; //初始为0
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v,w=e[i].w;
if(v==pre)
continue;
DP(v,u);
len=max(len,d[u]+d[v]+w); //更新直径
d[u]=max(d[u],d[v]+w);
}
}
该方法要遍历两次,第一次任选结点为根进行DFS,找到距离最远的结点;第二次以该距离最远的结点为根进行DFS,找到距离最远的结点,两点距离即为直径大小,两点简单路径即为直径。
设 d i s t [ i ] : dist[i]: dist[i]:表示 i i i结点到根结点的距离
int dist[maxn],s,max_dist;
void DFS(int u,int pre)
{
if(dist[u]>max_dist)
{
max_dist=dist[u];
s=u;
}
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].v,w=e[i].w;
if(v==pre)
continue;
dist[v]=dist[u]+w;
DFS(v,u);
}
}
int get_len()
{
max_dist=dist[1]=0;
s=1;
DFS(1,-1);
max_dist=dist[s]=0;
DFS(s,-1);
return max_dist;
}
cs