题目:1078. 旅游规划
思路:求出每个结点i的最大子长度和次大子长度(中途可以求出maxd),以及父节点的最大长度,然后再在这三个长度里面选出最大的两个求其和,并判断是否和maxd相等
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<double,double>PII;
const int N=2e5+10;
const int mod=1000000009;
int d1[N],d2[N],s1[N],fat[N];//d1[i]用于记录i的子结点中最大长度
//d2[i]用于记录i的子结点中次大长度
//s1[i]用于记录i的子结点中最大长度的子节点
//fat[i]用于记录父结点中最大的长度
vector<int >g[N];
int maxd=0;
void dfs1(int u,int fa){
for(int i=0;i<g[u].size();i++){
int t=g[u][i];
if(t!=fa){
dfs1(t,u);
int dis=d1[t]+1;
if(dis>d1[u]){//更新最大长度
d2[u]=d1[u],d1[u]=dis,s1[u]=t;
}else if(dis>d2[u]){//更新次大长度
d2[u]=dis;
}
}
}
maxd=max(maxd,d1[u]+d2[u]);
}
void dfs2(int u,int fa){
for(int i=0;i<g[u].size();i++){
int t=g[u][i];
if(t!=fa){
fat[t]=fat[u]+1;
if(t==s1[u]){//当t在u的最大长度上时
fat[t]=max(fat[t],d2[u]+1);
}else{//当t不在u的最大长度上时
fat[t]=max(fat[t],d1[u]+1);
}
dfs2(t,u);
}
}
}
int main(){
int n;
cin>>n;
int x,y;
for(int i=0;i<n;i++){
scanf("%d%d",&x,&y);
g[x].push_back(y);
g[y].push_back(x);
}
dfs1(0,-1);//先求出子节点的最大长度d1[i]和子节点的次大长度d2[i]
dfs2(0,-1);//然后求结点中父节点的最大长度fa[i]
for(int i=0;i<n;i++){
int t[3]={d1[i],d2[i],fat[i]};
sort(t,t+3);
if(t[1]+t[2]==maxd)
printf("%d\n",i);
}
return 0;
}