这道题我看大家都用 dijkstra 啊,惊恐,这里提供一种换根 dp 的写法。
两点间最短路径,那一定是 LCA 没错了。用一遍 dfs 求出根节点到每个点的距离,记为 \(dist\)。那么 \(u,v\) 间最短路径长度就是 \(dist_u+dist_v-dist_{\operatorname{lca}(u,v)}\times 2\)。
但是题目还要求至少经过一个关键点。如果 \(u,v\) 间的路径上存在关键点,那自然是好的,直接走就可以了;若不存在,则需要找一个路径上的点,使这个点向外走到一个关键点再回来的距离最小。
形式化地说,若路径长为 \(L\),每个点 \(i\) 到关键点的最近距离为 \(f_i\),则答案 \(ans=L+\min{f_i}\times 2\),其中点 \(i\) 在 \(u\) 到 \(v\) 的路径上。