【树上算法】树的直径

树的直径

一、什么是树的直径

直径往往和圆有关系。数学中,圆的直径是圆内最长的一条线段。那么在树中,树的直径就是树中最长的一段距离。

二、计算树的直径的思路

命题:
①在树上任取一个点x,找到距离x最远的一个点,即为y。y就是直径的一段。
②再找到距离y最远的一个点,即为z。这时候,y->z的路径就是树的直径了。

证明命题:(分①②两步证)

①:任取一点,距离这个点最远的点就是直径的一段。

分两种情况。

情况一:x点位于直径上。
在直径上的话图大概是长这样的。
直径的一段(y) 若干节点 选取的点(x) 若干节点 直径的另一段(z)
x → y x→y xy x → z x→z xz中必然有一个是较长的,y或z中的一个也肯定是距离x最远的点。

你可能会担心:要是有另外一个点w是距离x最远的点呢?
其实这个担心是多余的。
按刚才所想的那样,现在有三条路通向x节点,分别是:x->y(长度为a),x->z(长度为b),x->w(长度为c)。
我们要选择其中最长两条相连接作为直径。
若c>a或c>b,那么最长的两条就是(c,a)或者(c,b)了,而不是命题中所提到的 ( y → x → z ) (y→x→z) (yxz)这条路。

情况二:x点位于直径外。
其实这个证明方法与情况一相似,只需要注意一点:将x->y或x->z转化为另一条路径(先到直径上的一点再到直径的端点)即可。

②:知道了直径的一段,选最远的一个点,相连即为直径。

这个就不用证明了吧,就是定义啊。

三、计算树的直径的代码

这里就需要一个重要的函数——用于计算距离最远的点。
可以用 d f s dfs dfs实现。因为这道题的特殊性,所以树要用无向图存储。所以还要加一个参数 l a s t last last,表示上一次遍历的点,下一次就不能访问了,否则会导致死循环。
代码:

int point, mx = -1;
void dfs(int u, int last, int dis){
	if(dis > mx){
		mx = dis;
		point = u;
	}
	for(int i = 0; i < G[u].size(); i++){
		int v = G[u][i].first;
		int w = G[u][i].second;
		if(v == last)continue;
		dfs(v, u, dis + w);
	}
}

调用时很简单:

dfs(1, -1, 0);
mx = -1;//这是一个易错点,要记得初始化。
dfs(point, -1, 0);
cout << mx << endl;
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值