WA on #2,50 pts,思路简单,求大佬调代码。
查看原帖
WA on #2,50 pts,思路简单,求大佬调代码。
658786
STUDENT00楼主2023/11/16 18:54

RT,思路为:

1.求出每个点的深度 depdep,令 dep1=0dep_1=0。

2.将点按 depdep 降序排序,得到数组 idid。

3.二分答案,l=1,r=nl=1,r=n。

4.checkcheck 函数判断是否可在 kk 步内得到一棵深度为 dd 的树。

5.checkcheck 函数遍历 idid,如果没被染过色,就将其 d−1d-1 级祖先的子树染色,并将 res+1res+1。

6.判断 resres 是否 ≤k\le 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;
}
2023/11/16 18:54
加载中...