https://gmoj.net/senior/#main/show/5051
Solution
首先注意到每个点有且只有一条出边,也就是说这是一个环套树(森林)。
那么我们可以贪心。
首先这个森林里入度为零的点一定要跟root连边,因为没有任何其他的点可以到入度为零的点,然后就可以通过这些点更新其他的点。这个可以用拓扑来完成。
我们设dis数组表示每个点到root的距离,在拓扑中,如果我们遇见了一个dis>k且入度为零的点,那么就将它和root连边。
这样子树就处理完了,那么我们来考虑环。
不需要额外连边的环可以先判掉,然后对于其他环上已经被更新过的点,先用它们去尝试更新其他点。
那么问题就可以转化为:现在有一个环,环上有一些点已经染了色,我们可以花费1的代价,将一条长为k的链上的点全部染色,要求代价最小。
这个问题的做法是:
先把环剖开,(长度为n的环变成长度为2n的线段),预处理出一个next数组(表示一个点只经过染色点,最远可以到达的点)。
然后设f[i][j]表示第i个点,花费2j的代价,最远能到达的点。我们可用next处理出f[i][0]。
然后从1~n每个点开始跳,求出最少跳几次距离能>n,倍增优化跳跃,取min即可。