hihocoder周赛(树的最长距离)

题目4 : 道路建设

时间限制: 20000ms
单点时限: 1000ms
内存限制: 256MB

描述

H 国有 n 座城市和 n-1 条无向道路,保证每两座城市都可以通过道路互相到达。现在 H 国要开始施工,施工分若干个阶段,第 i 个阶段会建设无向道路 (x,y) ,当且仅当存在一个数 z,满足 x ≠ z, x ≠ y, z ≠ y,且在第 i-1 个阶段后,存在无向道路 (x,z), (z,y).

现在 H 国的国王想知道,在几个阶段后,每两个不同的城市之间都有一条无向道路.

输入

第一行一个正整数 n

接下来 n-1 行,每行两个正整数 (x,y),描述一开始的一条无向道路 (x,y)

1 ≤ n ≤ 105

输出

输出最少几个阶段后,每两个不同的城市之间都有一条无向道路.



#include<bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
vector<int>g[N];
int first[N], second[N];//first 存储到达最远结点的长度,second记录次长度
int res = 0;
void dp(int u, int pre) {
int k = g[u].size();
for(int i = 0; i < k; i++) {
if(g[u][i]==pre)continue;///子结点 == 父结点编号 边重复不需要重复扫
dp(g[u][i],u);
/**当子结点的最长边+1 (加上到父结点的距离1)大于父结点的最长边 更新父结点的最长边和次长边**/
if(first[g[u][i]]+1>=first[u])second[u]=first[u],first[u]=first[g[u][i]]+1;
else if(first[g[u][i]]+1>second[u])second[u]=first[g[u][i]]+1;
}
/**在以当前结点为根节点的子树中,最远两个结点的距离为first+second**/
res = max(res, first[u]+second[u]);
return ; 
}
int main() {
// freopen("data.in","r",stdin);
int n,u,v;
scanf("%d",&n);
for(int i=1; i<n; i++) {
scanf("%d %d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
dp(1,0);
long long ans = ceil(log2(res*1.0));
cout<<ans<<endl;
}

猜你喜欢

转载自blog.csdn.net/linruier2017/article/details/81052553