题目描述
给一棵以 为根、共 个结点的有根树。换根类问题有两种经典做法:
- 做法一(逐点换根):把 每个点轮流当一次根。每换一个根,就从新的根出发,把整棵树完整遍历一遍。
- 做法二(两遍扫描):固定以 为根,只扫两遍:第一遍自底向上(后序)扫整棵树,第二遍自顶向下(前序)再扫整棵树。
一遍完整遍历,无论从哪个点出发,都会把树上的 个点每个恰好进入一次。请你分别算出两种做法的总访问次数,输出这两个数。
树的形态不影响本题答案,但输入中仍然给出一棵具体的树,请照常读入。
输入格式
第一行一个整数 ,表示结点数。
接下来 行:第 行一个整数 (),表示结点 的父结点。
时没有任何父结点行。
输出格式
共两行:第一行输出做法一的总访问次数;第二行输出做法二的总访问次数。
样例
输入
1
输出
1 2
输入
5 1 2 3 4
输出
25 10
数据范围
- 注意:做法一的总访问次数最大可达 ,超出 32 位有符号整数的表示范围
背景知识
访问次数:一次遍历过程中,每进入一个结点,就记一次访问。把整棵树完整扫一遍,无论树长什么样、从哪个点出发,都恰好访问 次——因为每个点各被进入一次。
据此可以数账:做法一共要跑 遍,总访问次数是 个 相加,即 ;做法二只跑 遍,总访问次数是 个 相加,即 。两份程序算出的换根答案完全相同,访问次数却差了约 倍——把 与 换算成具体数字,正是估计程序会不会超时的第一步。
时树上只有 个点:做法一遍历 遍共访问 次,做法二要遍历 遍共访问 次。数据很小的时候遍数多的做法反而访问更多,这说明复杂度刻画的只是数据变大时的增长趋势。