衆所周知的兩種求法:數組
最深
指按照邊長算距離根節點最遠。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); } }