Description
给你一棵树,树上有N个点,编号从0到N-1
请找出任意一条树的直径,并输出直径上的点,输出顺序为从直径的某个端点走向另一个端点
Format
Input
第一行一个整数 n;
之后 n-1 行每行两个整数 u,v,表示 u 和 v 之间有边。
1<=N<=2e5
Output
如题
Samples
输入数据 1
10
0 1
0 2
0 4
0 6
0 7
1 3
2 5
4 8
6 9
Copy
输出数据 1
3 1 0 2 5
思路
是树的直径的加难板,不会的可以看看求树的直径(史上最详细,匠心之作)_树的直径存在负边权-CSDN博客
我们可以在求完树的直径的两个端点后再做一次dfs并用栈储存路径即可,详解代码。
代码
#include<bits/stdc++.h>
using namespace std;
vector<int>vec[1000001];
bool vis[10000001];
int ans,dep[1000001],n,x,y,len,t,tt,ttt,a[1000001],as;
stack<int> st;
void dfs(int nd,int deep)
{
dep[nd] = deep;
vis[nd] = 1;
for(int i = 0;i < vec[nd].size();i++)
{
int son = vec[nd][i];
if(vis[son] == 0)
{
dfs(son,deep + 1);
}
}
}
void dfs_2(int nd)
{
vis[nd] = 1;
st.push(nd);
if(nd == ttt)
{
while(st.size())
{
a[++as] = st.top();
st.pop();
}
for(int i = 1;i <= as;i++) cout<<a[i]<<' ';
exit(0);
}
for(int i = 0;i < vec[nd].size();i++)
{
int son = vec[nd][i];
if(vis[son] == 0) dfs_2(son);
}
st.pop();
}
signed main()
{
cin>>n;
for(int i = 1;i < n;i++)
{
cin>>x>>y;
vec[x].push_back(y);
vec[y].push_back(x);
}
dfs(0,1);
for(int i = 0;i < n;i++)
if(tt < dep[i])
{
tt = dep[i];
t = i;
}
memset(vis,0,sizeof(vis));
memset(dep,0,sizeof(dep));
tt = 0;
dfs(t,0);
for(int i = 0;i < n;i++)
{
if(tt < dep[i])
{
tt = dep[i];
ttt = i;
}
}
//t~ttt
memset(vis,0,sizeof(vis));
dfs_2(t);
return 0;
}