树的最长路径(最远点对,树的直径)学习笔记

树的最长路径

紫书第281页;

紫书这章讲的就是树上的动态规划,所以显然,求这个可以用动态规划求;

在求这个之前,要明白无论是树的最大独立集,树的重心,树的最长路径都是无根树,说白了就是没有告诉你根结点是什么。

所以不能指定 1 号点就一定为要求路径中的起点或必经之点;

这里还有一种dfs的写法,

先随便找一个点 p 为起点,用dfs求出 p 的最远点 q,然后再用 q 为起点,找出最远点 w ,

q到w的路径就为最远点,最长路径;

题目:

模板题

#include
#define ll long long
#define pa pair
#define lson k<<1
#define rson k<<1|1
#define inf 0x3f3f3f3f
//ios::sync_with_stdio(false);
using namespace std;
const int N=100100;
const int M=1000100;
const ll mod=998244353;
int n;
ll a[N];
int head[N];
struct Node{
	int to,nex;
}edge[N<<1];
int cnt;
void add(int p,int q){
	edge[cnt].to=q;
	edge[cnt].nex=head[p];
	head[p]=cnt++;
}
pa dfs(int so,int fa){
	pa p=make_pair(so,a[so]);
	for(int i=head[so];~i;i=edge[i].nex){
		int v=edge[i].to;
		if(v==fa) continue;
		pa s=dfs(v,so);
		if(a[so]+s.second>p.second){
			p=s;
			p.second+=a[so];
		}
	}
	return p;
}
int main(){
	ios::sync_with_stdio(false);
	memset(head,-1,sizeof(head));
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<n;i++){
		int p,q;
		cin>>p>>q;
		add(p,q);
		add(q,p);
	}
	pa p=dfs(1,-1);
//	cout<
	cout<<dfs(p.first,-1).second<<endl;
	return 0;
}

更新:

树的直径是树上最长的一条链;

但是真正常考的是树的中点,也就是树的直径中点;

树的中点性质:以树的中心为整棵树的根时,从该根到每个叶子节点的最长路径最短

这个和重心是有区别的;

你可能感兴趣的:(#,紫书笔记,#,树形结构)