/*18923 二叉树的直径
时间限制:1000MS 代码长度限制:10KB
提交次数:0 通过次数:0
题型: 编程题 语言: 不限定
Description
给定一棵二叉树,你需要计算它的直径长度。一棵二叉树的直径长度是任意两个结点路径长度中的最大值。这条路径可能穿过也可能不穿过根结点。
1
/ \
2 3
/ \
4 5
答案为3, 它的长度是路径 [4,2,1,3] 或者 [5,2,1,3]。
输入格式
共n行。
第一行一个整数n,表示有n个结点,编号为1至n。
第二行至第n行,每行有两个整数x和y,表示在二叉树中x为y的父节点。x第一次出现时y为左孩子
输出格式
输出二叉树的直径。
输入样例
5
1 2
1 3
2 4
2 5
输出样例
3
所谓二叉树的直径,就是以某一结点为根,左右子树深度之和减1
*/
#include<stdio.h>
#include<math.h>
int tree[100] = { 0 }; //用来存储树的节点数据
int treeNum[100] = { 0 };//出来存储树的节点是放在哪个序号
int diameter = 0;
void f(int p, int c)
{
if (tree[2 * treeNum[p]] == 0)
{
tree[2 * treeNum[p]] = c;//放数据
treeNum[c] = 2 * treeNum[p];//放数据的在树里面的序号
}//左子树没有被占用放左子树
else
{
tree[2 * treeNum[p] + 1] = c;
treeNum[c] = 2 * treeNum[p] + 1;
}//放在右子树
}
int dfs(int root)
{
if (tree[root] == 0) //访问到空结点,显然直径为0
{
return 0;
}
int left = dfs(2 * treeNum[tree[root]]); //后续求取左右子树的各自经过的最大结点数,不包括当前root
int right = dfs(2 * treeNum[tree[root]] + 1);
//后序操作,更新最长路径的值
if (diameter < left + right + 1)//因为L和R是 不包括当前结点 的子树的最深路径经过的结点数,因此,结果更新要加上当前root
diameter = left + right + 1;
if (left > right) //同理,返回当前子树最大深度经过的结点数
return left + 1;
else
return right + 1;
}
int main()
{
int n;
scanf("%d", &n);
if (n == 1)
{
printf("1");
return 0;
}//只有一个节点
int p, c;
scanf("%d %d", &p, &c);
tree[1] = p;
treeNum[p] = 1;
tree[2] = c;
treeNum[c] = 2; //第一次放入 只能手动处理了
for (int i = 1; i < n - 1; i++)
{
scanf("%d %d", &p, &c);
f(p, c);
}//录入节点情况
dfs(1);
printf("%d", diameter-1);
}