把二叉樹旋轉先模擬幾遍,要不然這個題。。。gg
模擬下葉子節點如何轉爲root
h:向下還能到達的深度
dep:所在的深度
lm:root到節點需要左移多少次
rm:root到節點需要右移多少次
這個方程還比較好理解,最後轉爲root的時候他的子樹的lm,rm,一定是這樣的距離
dp[root] = max(h[r[root]]+lm+1,h[l[root]]+rm+1);
關鍵是這部分:
lm++,dfs(l[root],max(last_max,h[r[root]]+lm+1));
lm--,rm++,dfs(r[root],max(last_max,h[l[root]]+rm+1));
rm--;
在這個節點作爲root的時候比它大(之前父節點,父節點的父節點。。。。)
也會成爲比它小的節點,這個就是這些節點用來更新此節點的,多模擬一下就會明白的
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <vector>
#include <cstring>
#include <cmath>
#include <map>
#include <queue>
using namespace std;
bool f[100005];//判斷是否有父節點
int l[100005],r[100005];
int root;
int h[100005];//向下還能到達的深度
int dep[100005];//所在的深度
int dp[100005];
int rm,lm;
int get_num(int root,int d){
if(!root){
dep[root] = dep[root] = 0;
return 0;
}
dep[root] = d;
h[root] = max(1+get_num(l[root],d+1),1+get_num(r[root],d+1));
return h[root];
}
void dfs(int root,int last_max){
if(!root)return;
if(!f[root]){
dp[root] = 1+max(h[l[root]],h[r[root]]);
}
else{
dp[root] = max(max(h[r[root]]+lm+1,h[l[root]]+rm+1),last_max);
}
lm++,dfs(l[root],max(last_max,h[r[root]]+lm+1));
lm--,rm++,dfs(r[root],max(last_max,h[l[root]]+rm+1));
rm--;
}
int main(void){
//freopen("in.txt","r",stdin);
int n,i;
while(cin >> n && n){
rm = lm = 0;
for(i=0;i<=n;i++){
f[i] = 0;
dp[i] = 0;
}
for(i=1;i<=n;i++){
int a,b;cin >> a >> b;
//cout << a << b << endl;
l[i] = a, r[i] = b;
f[a] = f[b] = true;
}
for(i=1;i<=n;i++){
if(!f[i]){
root = i;
break;
}
}
get_num(root,1);
dfs(root,0);
for(int i=1;i<=n;i++){
printf("%d\n",dp[i]);
}
}
}