[图论记录]AT2044 [AGC004D] Teleporter
command_block
2021-02-28 21:12:04
**题意** : 给出一个 $n$ 个点的有向图,每个点都有恰好一条出边。
保证每个点都能到达 $1$ 号点,现在要修改一些出边的目的地,使得从任意点出发走 $k$ 步都恰好到达 $k$。
问至少需要修改多少次出边。
$n\leq 10^5$ ,时限 $\texttt{1s}$。
------------
原图为一棵基环内向树。
首先不难发现需要将 $1$ 号点的出边改为自环。
由于每个点都能到达 $1$ 号点,所以 $1$ 必然在环上。
于是图会变为一棵内向树,目标是让所有点到根的距离都不超过 $k$。
设 $d[u]$ 为 $u$ 到子树内点的最大距离。
每次将 $d[u]=k-1$ 的所有点与 $1$ 直接相连,不断重复此过程,则可得到最优解。
可以用一次 $\rm dfs$ 以 $O(n)$ 的复杂度完成,具体见代码。
```cpp
#include<algorithm>
#include<cstdio>
#include<vector>
#define MaxN 100500
using namespace std;
vector<int> g[MaxN];
int n,k,ans,d[MaxN];
void dfs(int u,int fa)
{
for (int i=0;i<g[u].size();i++){
dfs(g[u][i],u);
d[u]=max(d[u],d[g[u][i]]);
}d[u]++;
if (d[u]==k&&fa>1){ans++;d[u]=0;}
}
int main()
{
scanf("%d%d",&n,&k);
for (int i=1,fa;i<=n;i++){
scanf("%d",&fa);
if (i==1)ans+=(fa!=1);
else g[fa].push_back(i);
}dfs(1,0);
printf("%d",ans);
return 0;
}
```