题意:
有一棵根节点为1的树,根节点处有无限个部队,每次操作你能让一个部队移动一步,问你最少移动多少次可以遍历完这个树。
题解:
非常巧妙的树形DP,跪了
#include<bits/stdc++.h> using namespace std; const int maxn=1e6+100; int n; vector<int> g[maxn]; int pre[maxn]; int dep[maxn]; int maxDep[maxn]; long long ans; void dfs1 (int u,int f) { dep[u]=dep[f]+1; maxDep[u]=dep[u]; for (int v:g[u]) { if (v!=f) { dfs1(v,u); maxDep[u]=max(maxDep[u],maxDep[v]); //更新距离它最远的叶子节点是多少 } } } long long dfs2 (int u,int f) { pre[u]=u; for (int v:g[u]) { if (v==f) continue; ans+=min(dep[u],dep[pre[u]]-dep[u]+1); dfs2(v,u); pre[u]=pre[v]; } } bool cmp (int x,int y) { return maxDep[x]<maxDep[y]; } int main () { int T; scanf("%d",&T); for (int k=1;k<=T;k++) { int n; scanf("%d",&n); ans=0; for (int i=2;i<=n;i++) { int x; scanf("%d",&x); g[x].push_back(i); g[i].push_back(x); } dfs1(1,0); for (int i=1;i<=n;i++) sort(g[i].begin(),g[i].end(),cmp); dfs2(1,0); printf("Case #%d: %lld ",k,ans); for (int i=1;i<=n;i++) g[i].clear(); } }