题目大意

定义 kk 阶刺猬树:

  • 对于 11 阶刺猬树,其中一个点的度 3\ge3,其它点的度均为 11
  • 对于 kk 阶刺猬树,是在 k1k−1 阶刺猬树的基础上,把所有度为 11 的点替换成 11 阶刺猬树,并与原图相连。

给定 nn 个点的树,判断是否是 kk 阶刺猬树。

思路

对于任意 kk 阶刺猬树,有性质:

  • 假定 aa 为原始 11 阶刺猬树的度 3\ge 3 的节点,则 aa 到所有叶子节点的距离均为 kk

而且只要满足此性质及为 kk 阶刺猬树。

证明:

假设 aa11 阶刺猬树的度 3\ge 3 的节点,那么所有的节点到 aa 的距离均为 11

22 阶刺猬树则将所有度为 11 的节点增加一层,及将 aa 到叶子节点的距离增加 11

对于 kk 阶刺猬树,aa 到叶子的节点均为 k1k-1 阶刺猬树到叶子的节点的距离加 11,所以 kk 阶刺猬树中 aa 到叶子节点的距离为 kk

相对的,将所有的叶子节点都向父节点移动,那么如果所有的移动经过 kk 次移动,到最后在一个节点汇合那么这棵树就是 kk 阶刺猬树。

AC Code

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+6;
int n,k,du[N];
bool vis[N];
vector<int> v[N];
queue<int> q[2];
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(nullptr);
	cin>>n>>k;
	if(k>n){
		cout<<"No\n";
		exit(0);
	}
	for(int i=1,x,y;i<n;i++){
		cin>>x>>y;
		v[x].push_back(y);
		v[y].push_back(x);
		du[x]++,du[y]++;
	}
	for(int i=1;i<=n;i++){
		if(du[i]==1){
			q[1].push(i);
			vis[i]=1;
			// cout<<i<<' ';
		}
	}
	// cout<<'\n';
	// exit(0);
	for(int i=1;i<k;i++){
		while(!q[i%2].empty()){
			int x=q[i%2].front();
			q[i%2].pop();
			for(int j:v[x]){
				if(vis[j]){
					continue;
				}
				if(du[j]<=3){
					cout<<"No\n";
					exit(0);
				}
				// cout<<j<<' ';
				vis[j]=1;
				q[(i+1)%2].push(j);
			}
		}
		// cout<<'\n';
	}
	int cnt=0,p;
	for(int i=1;i<=n;i++){
		if(!vis[i]){
			cnt++;
			p=i;
			if(du[i]<3){
				cout<<"No\n";
				exit(0);
			}
		}
	}
	if(cnt==1&&q[k%2].size()==v[p].size()){
		cout<<"Yes\n";
	}
	else{
		cout<<"No\n";
	}

	return 0;
}