算法:树形 DP + DFS
时间复杂度:$O(N)$
首先,这棵树采用邻接表的形式进行存储,方便查找。
然后,寻找这棵树的直径,则为每个节点子树长度的最大值和次大值之和再取其 MAX,而这可以通过树形 DP 来做,具体讲解为 AcWing 1072. 树的最长路径。
第一次做确实摸不着头脑。
C++ 代码
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 20010, M = 20010;
int n, m, ans;
int h[N], e[M], ne[M], idx;
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; // d1 表示最长路,d2 表示次长路
for (int i = h[u]; i != -1; 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);
return d1 + 1;
}
int main()
{
cin >> n >> m;
memset(h, -1, sizeof(h));
for (int i = 2; i <= n; ++i) {
int p;
cin >> p;
add(p, i); // p - i
}
for (int i = 1; i <= m; ++i) {
int p;
cin >> p;
add(p, n + i);
}
dfs(1);
cout << ans << endl;
return 0;
}