题目
310.最小高度树
题目大意
树是一个无向图,其中任何两个顶点只通过一条路径连接。 换句话说,一个任何没有简单环路的连通图都是一棵树。
给你一棵包含 n
个节点的树,标记为 0
到 n - 1
。给定数字 n
和一个有 n - 1
条无向边的 edges
列表(每一个边都是一对标签),其中 edges[i] = [ai, bi]
表示树中节点 ai
和 bi
之间存在一条无向边。
可选择树中任何一个节点作为根。当选择节点 x
作为根节点时,设结果树的高度为 h
。在所有可能的树中,具有最小高度的树(即,min(h)
)被称为 最小高度树 。
请你找到所有的 最小高度树 并按 任意顺序 返回它们的根节点标签列表。
树的 高度 是指根节点和叶子节点之间最长向下路径上边的数量。
样例
示例 1:
输入:n = 4, edges = [[1,0],[1,2],[1,3]]
输出:[1]
解释:如图所示,当根是标签为 1 的节点时,树的高度是 1 ,这是唯一的最小高度树。
示例 2:
输入:n = 6, edges = [[3,0],[3,1],[3,2],[3,4],[5,4]]
输出:[3,4]
数据规模
提示:
- 1 < = n < = 2 ∗ 1 0 4 1 <= n <= 2 * 10^4 1<=n<=2∗104
edges.length == n - 1
0 <= ai, bi < n
ai != bi
- 所有
(ai, bi)
互不相同 - 给定的输入 保证 是一棵树,并且 不会有重复的边
思路
题目中给定的含有 n n n个节点的树,有如下特点:
- 树中的共有 n − 1 n-1 n−1 条不同的边;
- 任意两个节点之间有且仅有一条路径;
- 叶子节点的度为 1 1 1,非叶子节点的度至少为 2 2 2;
- 树的高度由根节点到叶子节点的最大距离决定。
考虑常规做法,就是寻找最长链,而寻找最长链的方法就是先随机选择一个节点(比如
0
0
0号节点)开始遍历,找到离
0
0
0号节点的最远的节点
x
x
x(可能不止一个,随便选择一个即可),然后再以
x
x
x作为起点遍历,找到离
x
x
x最远的节点
y
y
y,那么路径
x
→
y
x\rightarrow y
x→y就是最长链,然后用pre
数组记录回边,用path
导出最长链。如果最长链的结点数是奇数,那么边数就是偶数,刚好最中间的点就是所求的根节点;如果最长链的结点数是偶数,那么边数就是奇数,刚好最中间的两个点就是所求的根节点。
代码
// short int long float double bool char string void
// array vector stack queue auto const operator
// class public private static friend extern
// sizeof new delete return cout cin memset malloc
// relloc size length memset malloc relloc size length
// for while if else switch case continue break system
// endl reverse sort swap substr begin end iterator
// namespace include define NULL nullptr exit equals
// index col row arr err left right ans res vec que sta
// state flag ch str max min default charray std
// maxn minn INT_MAX INT_MIN push_back insert
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int>PII;
typedef pair<int, string>PIS;
const int maxn=3e4+50;//注意修改大小
long long read(){long long x=0,f=1;char c=getchar();while(!isdigit(c)){if(c=='-') f=-1;c=getchar();}while(isdigit(c)){x=x*10+c-'0';c=getchar();}return x*f;}
ll qpow(ll x,ll q,ll Mod){ll ans=1;while(q){if(q&1)ans=ans*x%Mod;q>>=1;x=(x*x)%Mod;}return ans%Mod;}
class Solution {
public:
void dfs(int u,vector<int>&dist,vector<int>&pre,vector<vector<int>>&e){
for(auto v:e[u]){
if(!dist[v]){
dist[v]=dist[u]+1;
pre[v]=u;
dfs(v,dist,pre,e);
}
}
}
int find(int u,vector<int>&pre,vector<vector<int>>&e){
int n=e.size();
vector<int>dist(n);
dist[u]=1;
dfs(u,dist,pre,e);
int maxdist=0,x=-1;
for(int i=0;i<n;i++){
if(dist[i]>maxdist){
maxdist=dist[i];x=i;
}
}
return x;
}
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
if(n==1){
return {0};
}
vector<vector<int>>e(n);
vector<int>pre(n,-1);
for(auto it:edges){
e[it[0]].push_back(it[1]);
e[it[1]].push_back(it[0]);
}
int x=find(0,pre,e);
int y=find(x,pre,e);
pre[x]=-1;
vector<int>path;
while(y!=-1){
path.push_back(y);
y=pre[y];
}
if(path.size()%2){
return {path[path.size()/2]};
}
else{
return {path[path.size()/2-1],path[path.size()/2]};
}
}
};