算法笔记 - 树的直径

树的直径

定义 性质:

树的直径是树上最长的链,即树上任意两点间距离的最大值,可能有多条。

若树无边权,则所有直径的中点相同。

求法:

两次 \(DFS\)

第一次,以任意节点为根,搜索到距离自己最远的点,这个点就是直径的一个端点。

第二次,以第一次求得的点为根,搜索到距离自己最远的点,这个点就是另一个端点。

长度和路径可以在 \(DFS\) 中求得。

时间复杂度:\(\Theta(N)\)

代码:

#include<iostream>
#include<vector>
#include<cstring>
#define int long long
using namespace std;

const int N = 100010;

int n;
vector<int> G[N];
int le, n1, n2, dia[N]; // 直径长度,一个端点,dfs次数,节点
int de[N];

void predfs(int u, int fa)
{
	if(de[u] > le)
	{
		le = de[u]; // 更新长度
		n2 = u; // 更新端点
	}
	for(int i=0; i<G[u].size(); i++)
	{
		int v = G[u][i];
		if(v == fa)
			continue;
		de[v] = de[u] + 1;
		if(n1)
			dia[v] = u; // 存储路径
		predfs(v, u);
	}
}

signed main()
{
	cin >> n;
	for(int i=1; i<n; i++)
	{
		int u, v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	predfs(1, 0);
	memset(de, 0, sizeof(de));
	le = 0, n1 = n2;
	de[n2] = 1;
	predfs(n2, 0);
	cout << n1 << ' ' << n2 << ' ' << le << '\n';
    // 端点和长度
	int t = n2;
	for(int i=1; i<=le; i++)
	{
		cout << t << ' ';
		t = dia[t];
	} // 路径
	return 0;
}

热门相关:来自异世界的诺诺   美食萌后:皇上,休了你   傲天弃少   傲天弃少   九阳剑圣