对y总代码进行注释,方便自己理解和复习。与此同时,方便别的同学参考。
这道题是树的直径的模板题,前提是能识别出来。
首先,问题很明显,求图(树)任意两点距离的最大值,这在树中的定义就是树的直径。这条路径称为树的最长链。
然后,这种模板题在提高课讲过,放在树形dp那里讲的。
讲的做法是dfs,遍历每个点,以该点作为最高点,求它的儿子们从上到下路径长度的最大值和次大值,加起来就是最高点的最大路径长。
#include<bits/stdc++.h>
using namespace std;
const int N = 20010, M = N;
int n, m;
int h[N],e[M],ne[M],idx;
int ans;
void add(int a, int b){
e[idx] = b, ne[idx] = h[a], h[a] = idx ++;
}
int dfs(int u){
int d1 = 0, d2 = 0; // 最大距离和次大距离
// 遍历所有的儿子
for(int i = h[u]; ~i; i = ne[i]){
int j = e[i];
int d = dfs(j); //返回儿子j自上而下的最大距离
if( d >= d1) d2= d1, d1= d;
else if( d > d2) d2 = d;
}
ans = max(ans, d1 + d2); // 以u为最高点的链的最大值
// 边权为1,a --> b --> c,d1是b-->c的距离,还得加上a-->b的距离1
return d1 + 1;
}
int main(){
cin >> n >> m;
memset(h, -1, sizeof h);
// 交换机和电脑等价,直接读入
//交换机的编号1~n,电脑的编号n + 1 ~ n + m,
for(int i= 2; i <= n + m; i ++){
int p;
cin >> p;
add(p, i); // 连一条p到i的边,根到儿子的边
}
dfs(1); // 从根结点遍历
cout << ans << endl;
}