题目描述
给出每个节点的两个儿子节点,建立一棵二叉树,如果是叶子节点,则输入0 0。建好树后希望知道这棵二叉树的深度。二叉树的深度是指从根节点到叶子结点时,最多经过了几层。
最多有 10^6个结点。
传送门
这个是昨天做的一个题目,看到好多大犇分分钟AK全场,比赛的时候看了20分钟没看懂题意…(虽然当时有想法),哎~,以后有想法就得先尝试一下,万一对了呢!!!
个人觉得这个题目对这个输入的数据没有描述的清楚(可能就是用题意卡一部分人),我们可以从他给出的样例可以推测一下:
根节点就是1
然后添加1的左节点2,右节点7
然后添加2的左节点3,右节点6
然后添加3的左节点4,右节点5
观察可以发现这个值可能就是建树的编号,过程就是深搜+回溯
因此我就先统计共有多少组非两个数0,然后输出组数+1,交到oj对了2/5,从而个人觉得这个思路是么得问题的!!!
然后自己推测了另一组数据:
7
2 7
3 6
0 0
0 0
4 5
0 0
0 0
然后发现这组数据是不可行的…
因此又推测了一组数据:
7
2 5
3 4
0 0
0 0
6 7
0 0
0 0
这个的结果应该是3
写到这里,应该就可以发现就是下标作为父节点,值为节点的值,因此我们需要开两个个数组,分别存放右节点和左节点,然后直接dfs+回溯判断深度即可~
这个题最重要的应该是利用数组下标记录父节点,不然可能会超时,因为最多有10^6个节点。
AC以后看了一些AC代码,大犇用树状dp,还有一些与我类似的写法,大犇叫做记忆化搜索,原来下标记录法的dfs就是记忆化搜索~,又学到了!!!
AC代码
#include<bits/stdc++.h>
using namespace std;
int n,t,ans;
vector<int>l,r;
void dfs(int now,int walk){
if(l[now]==0&&r[now]==0){
if(walk>ans) ans=walk;
}else{
dfs(l[now],walk+1);
dfs(r[now],walk+1);
}
}
int main(){
l.push_back(0);
r.push_back(0);
scanf("%d",&n);
for(int i=1;i<=n;i++){
int ls,rs;
scanf("%d%d",&ls,&rs);
l.push_back(ls);
r.push_back(rs);
}
dfs(1,1);
printf("%d",ans);
return 0;
}