芭芭拉冲鸭~(dfs树两点最大距离)

树上两节点的最大距离

牛客网:题目链接:
感悟:
1.dfs的再理解,对树的遍历,用深度标记到根节点的距离。
2.树两点的最大距离的求解。

题意

给定一棵无根树,树上每个节点被染成了红色或绿色或蓝色。(R=红色,G=绿色,B=蓝色)
一条边两个节点的颜色不同芭芭拉才能冲刺(即能形成一条边),问芭芭拉在这一颗树上能冲刺的最远距离
(不能重复经过一条边) 重点喔

思路:

实际是求树上两节点的最大距离,由于颜色相同的节点芭芭拉不能通过,就会使得树分割成多颗树,
保留根节点和子节点,用dfs遍历树的最大和次大深度,每次dfs之后,两深度之和的距离是以该根节点的最大距离,取其中距离最大的。
再解释一波
拿个图来解释一下吧:
在这里插入图片描述
1号节点, 那么经过他的最大距离是:顺序为一 1 五。 五:最大深度路线 。一:次大深度路线 1号节点。他的和为5+3=8;下面以次。
2号节点, 最大距离是:顺序为 一 2 二
3号节点 , 最大距离是:顺序为三 3 五
4号节点, 最大距离是: 顺序为 四 4 五。
然后找出最大的距离。
可以发现在寻找一个节点时,先把它当成根,找以他为根起点的的最大深度路线和次大深度路线。
在分析一下吧,为什么要这么执行就一定可以得到树上两节点的最大距离。
要求到最大距离:那必然是从叶子节点出发到叶子节点结束。
(这里就不赘述了,多思考思考吧。假设不是叶子节点出发那会怎么样???,反之易得。。。)

题解代码如下:

#include<iostream>
#include<vector>
using namespace std;
#define ll long long
const int maxn=3e5+10;
vector<int>  a[maxn];
int fa[maxn],visit[maxn];
int n;
char s[maxn];
int maxdistance;
int shendu(int x,int y){ //y是x的子节点,返回以y为根的树的最大深度 
 	visit[y]=1;
 	int max1=0,max2=0; //最大,次大
 	int ans;
	for(int i=0;i<a[y].size();i++){
		int v=a[y][i];
		if(visit[v]||v==x) continue;
		ans=shendu(y,v);
		if(ans>max1){
			max2=max1;
			max1=ans;
		}else if(ans>max2){
			max2=ans;
		}
	}
	maxdistance=max(maxdistance,max1+max2);
	return max1+1; 
}
int main (){
	 cin>>n;
	 cin>>s+1;
	 int u,v;
	 for(int i=1;i<=n-1;i++){
	 	cin>>u>>v;
	 	if(s[u]!=s[v]){
	 		a[u].push_back(v);
	 		a[v].push_back(u);
		 }
	 }
	 for(int i=1;i<=n;i++){ //多个树,非连通 
	 	if(!visit[i]){
	 		shendu(0,i);
		 }
	 }
	 cout<<maxdistance<<endl;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

axtices

谢谢您的打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值