RT,思路为:
1.求出每个点的深度 dep,令 dep1=0。
2.将点按 dep 降序排序,得到数组 id。
3.二分答案,l=1,r=n。
4.check 函数判断是否可在 k 步内得到一棵深度为 d 的树。
5.check 函数遍历 id,如果没被染过色,就将其 d−1 级祖先的子树染色,并将 res+1。
6.判断 res 是否 ≤k。
错误信息:wrong answer 246th numbers differ - expected: '2', found: '1'。
简洁的代码:
#include<bits/stdc++.h>
using namespace std;
const int N=200005;
int T;
int n,k;
int head[N],nxt[N],ver[N],tot;
int fak[N],dep[N];
int stck[N],top;
int id[N];
int vis[N];
void add(int u,int v){
ver[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
void init(){
for(int i=1;i<=n;i++) head[i]=0;
tot=0;
}
void dfs_init(int u){
if(u^1) dep[u]=dep[stck[top]]+1;
stck[++top]=u;
for(int i=head[u];i;i=nxt[i]) dfs_init(ver[i]);
top--;
}
void dfs_calc(int u,int d){
stck[++top]=u;
if(top>=d) fak[u]=stck[top-d+1];
for(int i=head[u];i;i=nxt[i]) dfs_calc(ver[i],d);
top--;
}
void color(int u){
vis[u]=1;
for(int i=head[u];i;i=nxt[i]){
int v=ver[i];
if(vis[v]) continue;
color(v);
}
}
bool cmp(int x,int y){
return dep[id[x]]>dep[id[y]];
}
bool check(int d){
dfs_calc(1,d);
for(int i=1;i<=n;i++) vis[i]=0;
int res=0;
for(int j=1,i=id[1];j<=n;i=id[++j]){
if(dep[i]<=d) break;
if(vis[i]) continue;
res++;
color(fak[i]);
}
return res<=k;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&k);
init();
for(int v=2;v<=n;v++){
int u;scanf("%d",&u);
add(u,v);
}
dfs_init(1);
for(int i=1;i<=n;i++) id[i]=i;
sort(id+1,id+n+1,cmp);
int l=1,r=n,ans=-1;
while(l<=r){
int mid=l+r>>1;
if(check(mid)) ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
}
return 0;
}