[NFLS 1462/3] 岛屿 题解

大意

给定一个基环树森林, 求每棵基环树的直径之和.

题解

树上求直径很容易, 设 fuf_u 为以 uuuu 的子树中以 uu 为一端的最长链的值.

fu=max(fv+w), {v,w}edges(u),vfauf_u = max(f_v + w),\ \{v, w\} \in edges(u), v \not= fa_u,

resmax(res,fx+wx+fy+wy), {x,wx},{y,wy}edges(u),x,yfaures \leftarrow max(res, f_x + w_x + f_y + w_y),\ \{x, w_x\}, \{y, w_y\} \in edges(u), x, y \not= fa_u

而基环树则要考虑环.

考虑破环为链, 再扩大一倍.

那么 resmax(res,fi+fj+len(i,j)), 1i,j2n,ji<nres \leftarrow max(res, f_i + f_j + len(i, j)), \ 1 \le i, j \le 2 * n, |j - i| \lt n, 其中 nn 为环的长度.

使用前缀和, 贡献则变为 fj+len(1,j)+filen(1,i)f_j + len(1, j) + f_i - len(1, i).

考虑使用单调队列.

在队头, 每次弹出 ijni - j \ge n.

在队尾, 每次弹出 g(j)<g(i)g(j) < g(i), 其中 g(x)=fxlen(1,x)g(x) = f_x - len(1, x).

每次用队头元素更新即可.