P3884 [JLOI2009]二叉树问题题解

查看原题: P3884 [JLOI2009]二叉树问题

题目描述 如下图所示的一棵二叉树的深度、宽度及结点间距离分别为:

深度:4 宽度:4(同一层最多结点个数)

结点间距离: ⑧→⑥为8 (3×2+2=8)

⑥→⑦为3 (1×2+1=3)

注:结点间距离的定义:由结点向根方向(上行方向)时的边数×2,

与由根向叶结点方向(下行方向)时的边数之和。

在这里插入图片描述

输入格式
输入文件第一行为一个整数n(1≤n≤100),表示二叉树结点个数。接下来的n-1行,表示从结点x到结点y(约定根结点为1),最后一行两个整数u、v,表示求从结点u到结点v的距离。

输出格式 三个数,每个数占一行,依次表示给定二叉树的深度、宽度及结点u到结点v间距离

输入输出样例
输入 #1复制
10
1 2
1 3
2 4
2 5
3 6
3 7
5 8
5 9
6 10
8 6
输出 #1复制
4
4
8

思路: 树差分思想****LCA + ST; u 到 最近公共祖先节点距离 + v 到 最近公共祖先距离
题解:

/*
https://www.luogu.com.cn/problem/P3884
P3884 [JLOI2009]二叉树问题
*/
#include<bits/stdc++.h>
using namespace std;
const int N = 110;
int dep[N];
int f[N][20];
vector<int > g[N];
int n, m, s;

void dfs(int u, int p) {
	dep[u] = dep[p] + 1;
	for(int i = 1; i <= 19; i ++) {
		f[u][i] = f[f[u][i-1]][i-1];
	}
	int sz = g[u].size();
	for(int i = 0; i < sz; i ++) {
		int v = g[u][i];
		if(v == p)continue;
		f[v][0] = u;
		dfs(v, u);
	}
}

int LCA(int x, int y) {
	if(dep[x] < dep[y]) swap(x, y);
	for(int i = log2(dep[x]-dep[y]); i >= 0; i --) {
		if(dep[x]-dep[y] >= 1<<i) {
			x = f[x][i];
		}
	}
	assert(dep[x] == dep[y]);
	if(x == y) 	return x;
	for(int i = log2(dep[x]); i >= 0; i --) {
		if(f[x][i] != f[y][i]){
			x = f[x][i];
			y = f[y][i]; 
		}
	}
	assert(x != y && f[x][0] == f[y][0]);
	return f[x][0];
}
int main() {
	cin >> n;
	int u, v;
	for(int i = 1; i < n; i ++) {
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1, 0);
	cin >> u >> v;
	int max_dep = 0;
	int max_with = 0;
	int t_map[N];
	memset(t_map, 0, sizeof(t_map));
	for(int i = 1; i <= n; i ++) {
		max_dep = max(max_dep, dep[i]);
		t_map[dep[i]] ++;
	}
	for(int i = 1; i < 10; i ++) {
		max_with = max(max_with, t_map[i]);
	}
	int k = LCA(u, v);
	int ans = 2*(dep[u] - dep[k]) + dep[v] - dep[k];
	
	cout << max_dep << endl << max_with << endl << ans << endl;
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值