题目连接:传送门
题意:
给你一棵树,然后加一条边,加的这条边不能使树成环,求加边后从根节点出发的最长的路径。
分析:
如果可以加边的话那么这两个链一定是某个节点的最长链与次长链,然后一边dfs处理出所有的节点的深度,然后再一遍dfs求出所有点的最长链的长度与次长链的长度,然后枚举节点就可以了。
代码如下:
#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 1e5+10;
vector<int > vc[maxn];
int dept[maxn];
int mmax;
void init(){
for(int i=0;i<maxn;i++){
vc[i].clear();
}
mmax=0;
}
void dfs(int u,int dep){
dept[u]=++dep;
mmax = max(dep,mmax);
for(int i=0;i<vc[u].size();i++){
int v=vc[u][i];
dfs(v,dep);
}
}
int m[maxn][2];
int slove(int u){
if(m[u][0]) return m[u][0];
int m1=dept[u],m2=0;
for(int i=0;i<vc[u].size();i++){
int tmp = slove(vc[u][i]);
if(tmp<=m1&&tmp>m2&&m1!=dept[u]) m2=tmp;
if(tmp>m1){
if(m1!=dept[u])
m2=m1;
m1=tmp;
}
}
m[u][0]=m1;
m[u][1]=m2;
return m1;
}
int main()
{
int n;
while(~scanf("%d",&n)){
init();
for(int i=0;i<n-1;i++){
int u,v;
scanf("%d%d",&u,&v);
vc[u].push_back(v);
}
memset(m,0,sizeof(m));
dfs(1,0);
slove(1);
int ans = 0;
for(int i=1;i<=n;i++){
if(m[i][1])
ans=max(ans,m[i][0]-1+m[i][1]-dept[i]);
}
if(!ans) printf("%d\n",mmax-1);
else printf("%d\n",ans);
}
return 0;
}
/***
10
1 2
2 3
3 7
3 8
8 10
2 4
4 5
5 6
6 9
***/