牛客编程巅峰赛S2第5场 - 钻石&王者 C.Tree III
题目描述
给出一棵有n个节点的节点标号为1~n的有根树(根为第一个节点,并给出从第2个节点到第n个节点的父结点),请你求解它的“第二直径”的长度,即树上任意两点距离非严格的第二长距离为多少(也就是说,如果存在两条不同的,长度均为max的路径,则返回max)。
树:一张有n个节点,n-1条边的无向连通图。
示例1
输入
[1,2,3,4]
返回值
3
示例2
输入
[1,1,1,1]
返回值
2
图论定理,树的第二直径一定以树的直径的某一端为端点,求树的直径就是两段 DFS,然后再对直径的两端求一次 DFS,记录端点到其他所有点的距离,然后排序,显然第一第二大的为直径,第三大的就是第二直径,AC代码如下:
class Solution {
public:
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
* @param e int整型vector 长度为n-1的数组,表示结点2到结点n的父结点
* @return int整型
*/
const static int N=1e5+5;
int d[N],vis[N],mx,pos,s;
vector<int>g[N],ans;
void dfs(int u){
ans.push_back(d[u]);
vis[u]=1;
for(auto v:g[u]){
if(!vis[v]){
d[v]=d[u]+1;
if(d[v]>mx){
mx=d[v],pos=v;
}
dfs(v);
}
}
}
int tree3(vector<int>& e) {
for(int i=0;i<e.size();i++){
g[i+2].push_back(e[i]);
g[e[i]].push_back(i+2);
}
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
mx=0;
dfs(1);
ans.clear();
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
s=pos;
mx=0;
dfs(s);
memset(vis,0,sizeof(vis));
memset(d,0,sizeof(d));
s=pos;
mx=0;
dfs(s);
sort(ans.rbegin(),ans.rend());
return ans[2];
}
};