题目连接:传送门
题意:
给你一棵树,然后加一条边,加的这条边不能使树成环,求加边后从根节点出发的最长的路径。
分析:
如果可以加边的话那么这两个链一定是某个节点的最长链与次长链,然后一边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 ***/