树上两节点的最大距离
牛客网:题目链接:
感悟:
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;
}