题目
选择任意一个点跑到最远的点A,再以这个最远的点A为起点跑到最远的点B,AB之间的节点数就是树的直径。
原理:第一遍搜索肯定会跑到一个叶节点,从任意一个叶节点跑到最远的点,这个距离就是直径。
BFS
和DFS
都可以实现。
BFS代码:
struct node
{
ll v, w, next;
} edge[200010];
ll ct = 1;
ll head[200010];
inline void add(ll u, ll v, ll w)
{
edge[ct].v = v;
edge[ct].w = w;
edge[ct].next = head[u];
head[u] = ct++;
}
ll dis[200010];
bool vis[200010];
queue<int> q;
ll n;
ll bfs(ll s)
{
ll res;
fill(dis, dis + n + 1, INF);
fill(vis, vis + n + 1, 0);
dis[s] = 0;
q.push(s);
while (!q.empty())
{
s = q.front();
vis[s] = 1;
q.pop();
for (ll i = head[s]; i; i = edge[i].next)
{
if (vis[edge[i].v])
continue;
q.push(edge[i].v);
dis[edge[i].v] = dis[s] + edge[i].w;
res = edge[i].v;
}
}
return res; //返回最远结点编号
}
int main()
{
cin >> n;
ll u, v, w;
for (ll i = 1; i < n; i++)
{
scanf("%lld %lld", &u, &v);
add(u, v, 1);
add(v, u, 1);
}
ll s = bfs(1);
ll pos = bfs(s);
cout << dis[pos] << endl;
return 0;
}
DFS代码:
struct node
{
ll v, w, next;
} edge[200010];
ll ct = 1;
ll head[200010];
inline void add(ll u, ll v, ll w)
{
edge[ct].v = v;
edge[ct].w = w;
edge[ct].next = head[u];
head[u] = ct++;
}
ll dis[200010];
bool vis[200010];
ll n;
void dfs(ll s)
{
for (int i = head[s]; i; i = edge[i].next)
{
if (vis[edge[i].v])
continue;
vis[edge[i].v] = 1;
dis[edge[i].v] = dis[s] + 1;
dfs(edge[i].v);
}
}
int main()
{
cin >> n;
ll u, v, w;
for (ll i = 1; i < n; i++)
{
scanf("%lld %lld", &u, &v);
add(u, v, 1);
add(v, u, 1);
}
for (int i = 1; i <= n; i++)
dis[i] = INF, vis[i] = 0;
dis[1] = 0;
dfs(1);
ll pos;
ll maxx = 0;
for (int i = 1; i <= n; i++)
{
if (dis[i] > maxx)
{
maxx = dis[i];
pos = i;
}
}
for (int i = 1; i <= n; i++)
dis[i] = INF, vis[i] = 0;
dis[pos] = 0;
dfs(pos);
maxx = 0;
for (int i = 1; i <= n; i++)
if (dis[i] > maxx)
maxx = dis[i];
cout << maxx << endl;
return 0;
}