科丁乐K12137 二叉树中的秘密

题目描述
新年伊始,我飞买了一棵二叉树,传闻这棵二叉树的某一个节点上隐藏着上古的秘密,于是我飞开始昼夜不息的寻找。本着不遗漏任何一个节点的原则,飞神打算遍历整棵二叉树。
设S为飞神当前所处的节点。
若S有两个子节点L,R,则飞神总是先去遍历节点较少的那棵子树,然后再去遍历另一棵子树,若两棵子树的节点数相等,则飞神会先去遍历编号较小的那棵。

若S有一个子节点L,则飞神就去遍历以L为根结点的子树。

若S是叶子节点,则飞神会返回到S的父节点。

当飞神遍历完以S为根的子树时就会返回到S的父节点。

当飞神在某个节点发现宝藏时,遍历结束。

开始时,飞神在根结点。

现在给你一棵有n个节点的二叉树T,节点编号从1到n,节点1为根结点。

再给你藏有秘密的节点数X,请你计算出我飞需要访问的节点个数,重复访问的只记一次。

输入格式
多组输入,对于每组输入:

第一行包含一个整数n,x(1 <= x <= n <= 3*10^3),分别代表节点个数及藏宝节点编号。

接下来的n行,每行的第一个数为k(0 <= k <= 2),代表第i个节点的子节点个数。

继续读入k个整数,代表第i个节点的k个子节点,详见样例及提示。保证数据合法。

输出格式
对于每组数据,输出一个整数代表答案。

输入输出样例
输入样例1:
5 5
2 2 3
0
2 4 5
0
0
5 1
2 2 3
0
2 4 5
0
0
输出样例1:
5
1
说明
飞神的遍历路线为1->2->1->3->4->3->5。
科丁乐

【耗时限制】1000ms 【内存限制】128MB

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,x,ans,ok,cnt[2000000];
struct Node{
	ll l,r;
}t[200000];
ll count(ll r){
	if(!r)return 0;
	cnt[r]=count(t[r].l)+count(t[r].r)+1;
	return cnt[r];
}
void dfs(ll r){
	if(ok||!r)return;
	ans++;
	if(r==x)ok=1;
	if(cnt[t[r].l]<=cnt[t[r].r])dfs(t[r].l),dfs(t[r].r);
	else dfs(t[r].r),dfs(t[r].l);
}
int main(){
	while(~scanf("%lld%lld",&n,&x)){
		ans=ok=0;
		memset(t,0,sizeof t);
		for(ll	i=1;i<=n;i++){
			ll k,c[3]={0};
			scanf("%lld",&k);
			for(ll j=1;j<=k;j++)cin>>c[j];
			if(c[1]&&c[2]&&c[1]>c[2])swap(c[1],c[2]);
			t[i].l=c[1];
			t[i].r=c[2];
		}
		count(1);
		dfs(1);
		printf("%lld\n",ans);
	}
	
	return 0;
}

记得三连哦~~~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我是一只来自东方的鸭.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值