洛谷P15801[GESP202603 六级]完全二叉树

还是题目传送门

这题说实话,雀食很难。(我才不会告诉你我想了1个多小时)我认(kan)真(le)思(ti)考(jie)才知道这题要用DFS传输3个数据:是否为完全二叉树、是否为满二叉树、深度。

Solution

要知道这颗子树是否为完全二叉树,要判断这几个条件:

当自己的两颗子树深度相同时

1.当右子树为满二叉树且左子树也为满二叉树

2.当右子树为满二叉树且左子树为完全二叉树

当自己的两颗子树深度差为1时(且左子树较深)

1.当左子树为满二叉树且右子树也为满二叉树

2.当左子树为满二叉树且右子树为完全二叉树

如果不满足上述条件,则该子树不为完全二叉树,否则,该子树则为完全二叉树(第一种情况也为满二叉树)。

注意点

1.空树不仅是完全二叉树,也是满二叉树,只是深度为0。

2.要特判一下叶子节点。

AC Code

复制代码
#include<bits/stdc++.h>
using namespace std;
int n, ans = 0;
struct node{
	int lc;
	int rc;
}a[100020];
struct tj{
	int h;
	bool w;
	bool m;
};
tj sc(int d){
	if(a[d].lc == 0 && a[d].rc == 0){
		ans++;
		return {1, 1, 1};
	} 
	tj c1, c2;
	if(a[d].lc != 0){
		c1 = sc(a[d].lc);
	} else {
		c1 = {0, 1, 1};
	}
	if(a[d].rc != 0){
		c2 = sc(a[d].rc);
	} else {
		c2 = {0, 1, 1};
	}
	if(c1.h == c2.h){
		if(c1.m){
			if(c2.w){
				if(c2.m){
					ans++;
					return {c1.h + 1,1,1};
				}
				else{
					ans++;
					return {c1.h + 1,1,0};
				}
			}
			else{
				return {c1.h + 1,0,0};
			}
		} 
		else {
			return {c1.h + 1,0,0};
		}
	}
	else if(c1.h - 1 == c2.h){
		if(c2.m){
			if(c1.w){
				if(c1.m){
					ans++;
					return {c1.h + 1, 1, 0};
				} else {
					ans++;
					return {c1.h + 1, 1, 0};
				}
			} else {
				return {c1.h + 1, 0, 0};
			}
		} else {
			return {c1.h + 1, 0, 0};
		}
	} else {
		return {max(c1.h, c2.h) + 1, 0, 0};
	}
}
int main(){
	cin >> n;
	for(int i = 1; i <= n; i++)
		cin >> a[i].lc >> a[i].rc;
	sc(1);
	cout << ans;
	return 0;
}

总结

本题比较难想,富有逻辑,需要仔细思考。