众所周知的两种求法:数组
最深
指按照边长算距离根节点最远。void dfs_R1(int x, int fa, int depth) { if(depth > Max) Max = depth, Rs = x; for(int i = head[x]; i; i = edg[i].nxt) { if(edg[i].v == fa) continue; dfs_R1(edg[i].v, x, depth + edg[i].w); } } void dfs_R2(int x, int fa, int depth) { if(depth > ans) ans = depth, Re = x; for(int i = head[x]; i; i = edg[i].nxt) { if(edg[i].v == fa) continue; dfs_R2(edg[i].v, x, depth + edg[i].w); } }
f[x][1]
表示最长链,f[x][2]
表示次长链。更新时,若“链接儿子的边\(+\)此儿子子树中的最长链”大于当前最长链,则当前最长链变为次长链,最长链变为链接儿子的边\(+\)此儿子子树中的最长链,若大于次长链小于最长链则只更新次长链。树的直径必然为某一节点子树中的最长链\(+\)次长链。void dp_R(int x, int fa) { for(int i = head[x]; i; i = edg[i].nxt) { if(edg[i].v == fa) continue; dp_R(edg[i].v, x); if(edg[i].w + f[edg[i].v][1] > f[x][1]) f[x][2] = f[x][1], f[x][1] = edg[i].w + f[edg[i].v][1]; else if(edg[i].w + f[edg[i].v][1] > f[x][2]) f[x][2] = f[edg[i].v][1] + edg[i].w; ans = max(f[x][1] + f[x][2], ans); } }