查看原题: 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;
}