Codeforces Round #518 (Div. 1)B Multihedgehog(模拟,寻找多叉树的根,dfs)

该博客主要讨论了Codeforces Round #518 (Div. 1) B题——Multihedgehog的解决方案。博主解释了如何判断一个k叉树是否由k-1叉树构成,并提出了两种方法:通过求树的直径来寻找树根,或者通过逐层深入的方法。博主指出,每层结构相同,因此可以通过dfs递归k层进行判断,特别是需要处理好最后一层的情况。
摘要由CSDN通过智能技术生成

题目链接

题意

题目的意思挺难懂的,简单的来说,就是判断一个 k k k叉树是否由一个 k − 1 k-1 k1叉树而来。这里对 k k k叉树的定义是:

  1. 对于 1 1 1叉树,仅有一个点度数为 3 3 3且度数为 1 1 1的点个数大于等于3。
  2. 对于 k ( k ≥ 2 ) k(k\geq2) k(k2)叉树,是一个点连接 3 3 3个或 3 3 3个以上的 ( k − 1 ) (k-1) (k1)叉树所构成。

题解

这题主要就是需要找到树根,如果找到了树根那么就可以进行dfs判断是否为合格的k叉树,但如果找树根呢?一种办法是求出树的直径,然后根据直径长度的一半找到树根,还有一种方法便是,由于这颗树是一层一层扩展出去的,所以只要一层一层往里走,就可以找到树根,类似圆慢慢缩小。
因为每层都是一样的,所以dfs判断的话就是递归k层判断即可(注意特殊处理一下最后一层)。

代码

#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e5+5;
vector<int> G[maxn];
int que[maxn], l,r, de[maxn], pre[maxn];
void add(int f,int t) {
	G[f].push_back(t);
}
// 树的直径
int bfs(int o) {
	l = r = 0;
	que[r++] = o;
	memset(de, -1, sizeof de);
	de[o] = 0;
	pre[o] = -1;
	while(l <= r) {
		int u = que[l++];
		for(int i = 0; i < G[u].size(); ++i) {
			int to = G[u][i];
			if(de[to] != -1) continue;
			pre[to] = u;
			de[to] = de[u]+1;
			que[r++] = to;
		}
	}
	return que[r-1];
}

// 检验树根
bool check(int o, int fa, int k) {
	if(k == 0) {
		int son = 0;
		for(int i = 0; i < G[o].size(); ++i) {
			int to = G[o][i];
			if(to == fa) continue;
			son++;
		}
		if(son > 0) return false;
		return true;
	}
	int cnt = 0;
	for(int i = 0; i < G[o].size(); ++i) {
		int to = G[o][i];
		if(to == fa) continue;
		if(!check(to, o, k-1)) return false;
		cnt++;
	}
	if(cnt < 3)
		return false;
	return true;
}
int main() {
	int n,k,u,v;
	scanf("%d%d", &n, &k);
	for(int i = 0; i < n-1; ++i) {
		scanf("%d%d", &u, &v);
		add(u,v); add(v,u);
	}
	u = bfs(1);
	v = bfs(u);
	if(de[v]%2 != 0)
		puts("No");
	else {
		int center = v;
		for(int i = 0; i < de[v]/2; ++i)
			center = pre[center];
		// cout << center << endl;
		if(check(center, -1, k))
			puts("Yes");
		else 
			puts("No");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值