11688 uva 二叉樹的旋轉+dp Rotate to root

把二叉樹旋轉先模擬幾遍,要不然這個題。。。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]);
		}
	}
}




發佈了75 篇原創文章 · 獲贊 1 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章