这个模型非常的重要,同样也是非常的经典
设solve(u)返回的是以u为根节点的子树中的最长链
对于以u为根节点的子树,假如有n个子节点v
那么,先求出所有子节点的最长链,答案是什么呢?
当然是子节点的最长链+次长链!更新一下答案
然后再返回最长链,函数就ok了
所以随便确定一个根节点建树,然后求出分治求出所有的子树,再合并出答案,这题就差不多做完了~
要注意的地方:
1.不能走回头路,所以要标记一下,或者递归的时候传递父节点然后再判断,或者也可以用标记数组标记是否已被访问
2.开数组的时候,MX应该是两倍大小,不仅仅E数组要开两倍大小,Next数组也需要开两倍!
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long LL;
const int MX = 2e5 + 5;
int rear;
int Head[MX], Next[MX];
struct Edge {
int u, v;
} E[MX];
void edge_init() {
rear = 0;
memset(Head, -1, sizeof(Head));
memset(Next, -1, sizeof(Next));
}
void edge_add(int u, int v) {
E[rear].u = u;
E[rear].v = v;
Next[rear] = Head[u];
Head[u] = rear++;
}
int solve(int u, int from, int &ans) {
int Max1 = 0, Max2 = 0;
for(int id = Head[u]; ~id; id = Next[id]) {
int v = E[id].v;
if(v == from) continue;
int t = solve(v, u, ans) + 1;
if(t > Max1) {
Max2 = Max1;
Max1 = t;
} else if(t > Max2) Max2 = t;
}
ans = max(ans, Max1 + Max2);
return Max1;
}
int main() {
int n, last;
while(~scanf("%d", &n)) {
edge_init();
for(int i = 1; i <= n - 1; i++) {
int u, v;
scanf("%d%d", &u, &v);
edge_add(u, v);
edge_add(v, u);
last = u;
}
int ans = 0;
solve(last, -1, ans);
printf("%d\n", ans);
}
return 0;
}