主要介绍了树的两个性质,分别是路径和直径,1.求解详细路径 2.求解直径
求解路径
![](https://i-blog.csdnimg.cn/blog_migrate/69c72d37ac31e070d8672042d2e916b4.png)
求解路径的主要思路是先用vector容器edges建树,用pre数组记录来源节点(pre[i]表示i号节点的来源节点),然后利用pre数组从终点位置推演到起点位置,最后逆序输出答案即可
DFS
//求树上路径-DFS
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> edges[100001];
int pre[100001], ans[100001];
inline void dfs(int x){
for (auto y : edges[x]){
if (pre[x] != y){
pre[y] = x;
dfs(y);
}
}
}
int main(){
scanf("%d", &n);
for (int i = 1; i < n; i++){
int x, y;
scanf("%d%d", &x, &y);
edges[x].push_back(y);
edges[y].push_back(x);
}
int u, v;
scanf("%d%d",&u,&v);
pre[u] = -1;
dfs(u);
int l = 0;
for (int i = v; i != u; i = pre[i]){
ans[++l] = i;
}
ans[++l] = u;
for (int i = l; i >= 1; i--){
printf("%d ", ans[i]);
}
}
BFS
//求树上路径-BFS
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> edges[100001];
int pre[100001], ans[100001];
queue<int> q;
int main(){
scanf("%d", &n);
for (int i = 1; i < n; i++){
int x, y;
scanf("%d%d", &x, &y);
edges[x].push_back(y);
edges[y].push_back(x);
}
int u, v;
scanf("%d%d",&u,&v);
pre[u] = -1;
q.push(u);
while (!q.empty()){
int x = q.front();
q.pop();
for (auto y : edges[x]){
if (pre[x] != y){
pre[y] = x;
q.push(y);
}
}
}
int l = 0;
for (int i = v; i != u; i = pre[i]){
ans[++l] = i;
}
ans[++l] = u;
for (int i = l; i >= 1; i--){
printf("%d ", ans[i]);
}
}
求解直径
![](https://i-blog.csdnimg.cn/blog_migrate/f341e3997c859f213fdda52c72ea4aaf.png)
同样先用edges建树,用pre数组记录来源节点,先随便找一个点进行遍历(一般默认遍历1号节点吧,方便一些),找到距离这个点最远的点v,再遍历这个最远的点v,距离v最远的点的距离就是树的直径
DFS
//求树的直径-DFS
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> edges[100001];
int pre[100001], ans[100001], dis[100001];
inline void dfs(int x){
for (auto y : edges[x]){
if (pre[x] != y){
pre[y] = x;
dis[y] = dis[x] + 1;
dfs(y);
}
}
}
int main(){
scanf("%d", &n);
for (int i = 1; i < n; i++){
int x, y;
scanf("%d%d", &x, &y);
edges[x].push_back(y);
edges[y].push_back(x);
};
pre[1] = -1;
dfs(1);
int v = 0, temp = 0;
for (int i = 1; i <= n; i++){
if (dis[i] > temp){
temp = dis[i], v = i;
}
}
memset(pre, 0, sizeof(pre));
memset(dis, 0, sizeof(dis));
pre[v] = -1;
dfs(v);
int ans = 0;
for (int i = 1; i <= n; i++){
ans = max(ans, dis[i]);
}
printf("%d\n", ans);
}
BFS
//求树的直径-BFS
#include<bits/stdc++.h>
using namespace std;
int n;
vector<int> edges[100001];
int pre[100001], ans[100001], dis[100001];
queue<int> q;
inline void bfs(){
while (!q.empty()){
int x = q.front();
q.pop();
for (auto y : edges[x]){
if (pre[x] != y){
pre[y] = x;
q.push(y);
dis[y] = dis[x] + 1;
}
}
}
}
int main(){
scanf("%d", &n);
for (int i = 1; i < n; i++){
int x, y;
scanf("%d%d", &x, &y);
edges[x].push_back(y);
edges[y].push_back(x);
};
pre[1] = -1;
q.push(1);
bfs();
int v = 0, temp = 0;
for (int i = 1; i <= n; i++){
if (dis[i] > temp){
temp = dis[i], v = i;
}
}
memset(pre, 0, sizeof(pre));
memset(dis, 0, sizeof(dis));
pre[v] = -1;
q.push(v);
bfs();
int ans = 0;
for (int i = 1; i <= n; i++){
ans = max(ans, dis[i]);
}
printf("%d\n", ans);
}