( 数据结构专题 )【 树的直径 】
定义:我们将一棵树T = ( V,E )的直径定义为max ( u,v ) ( u,v ∈ V ),也就是说,树中所有最短路径距离的最大值即为树的直径。
怎么求树的直径呢?
1、两次bfs(或者dfs)
方法:先从任意一点P出发,找离它最远的点Q,再从点Q出发,找离它最远的点W,W到Q的距离就是是的直径。( 记住就好了 )
例题:http://115.236.49.52:83/contest/1351
题意概括:
给定一棵树,找出两个点x,y,设dis(x,y)表示x与y之间的距离,最大化max(ax,ay)·dis(x,y)。
我们只需要计算出距离每一个点最远的点有多远即可。
树的直径: 两端点是树上距离最远的两点
求直径时,只需要用DFS求出距离任意一个点最远的点x,再找出距离x最远的点y,即得到树的一对直径端点x、y。
设树的直径两端点分别为u,v,那么u或v必然距离点x最远。
所以我们只需要求出直径后从直径两端点分别DFS求出每个点到直径两端点距离值即可。
代码:
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n,via[200005],w[200005];
vector<int> G[200005];
int u[2],now;
int dep[200005];
void dfs( int x, int fa, int cnt, int op )
{
if ( cnt>now ) {
now = cnt;
u[op] = x;
}
for ( int i=0; i<G[x].size(); i++ ) {
int y = G[x][i];
if ( y==fa ) continue ;
dfs(y,x,cnt+1,op);
}
}
void dfs2( int x, int fa, int cnt )
{
dep[x] = max(dep[x],cnt);
for ( int i=0; i<G[x].size(); i++ ) {
int y = G[x][i];
if ( y==fa ) continue ;
dfs2(y,x,cnt+1);
}
}
signed main()
{
cin >> n;
for ( int i=1; i<=n; i++ ) scanf("%lld",&w[i]);
for ( int i=0; i<n-1; i++ ) {
int a,b;scanf("%lld %lld",&a,&b);
G[a].push_back(b);
G[b].push_back(a);
}
now = 0;
dfs(1,1,0,0);
now = 0;
dfs(u[0],u[0],0,1);
dfs2(u[0],u[0],0);
dfs2(u[1],u[1],0);
int ans = 0;
for ( int i=1; i<=n; i++ ) {
ans = max(ans,dep[i]*w[i]);
}
cout << ans << endl;
return 0;
}