树的直径
- 什么是树的直径?
树的直径指树中最远的两个节点之间的距离,连接这两个节点之间的路径被称为树的最长链。 - 树的直径的时间复杂度?
(O(N)) - 原理
我们通过两次DFS,第一次从任一点(S)出发进行DFS,找到一个离(S)最远的点(D),然后从(D)点出发,寻找离(D)点最远的点(E),(D)(E)之间的距离即为树的直径。 - 原理证明?
分三种情况
第一种,(P)在直径上,根据定义可知(PQ)为树的直径
第二种,(P)不在直径上
我们使用反证法
假设(PQ)不是直径,但(AB)是直径,则(OP+OQ>OP+OB),得(OQ+OA>OB+OA),即(QA>AB),与直径定义相悖,故原命题成立
第三种,(PQ)与(AB)无交点
依旧是反证法,(MP+MQ>MQ+MN+NB),同时减掉(MQ),得(MP>MN+NB),易知(MP+MN>NB),所以(MP+MN+NA>NB+NA),
即(MP+MN+NA>AB),与(AB)是直径矛盾,所以这种情况也不成立 - 代码实现
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7;
int n,m,tot = 0;
bool v[N];
int ans = 0,farp;
int ver[N],edge[N],Next[N],head[N],d[N];
void add(int x,int y,int z)
{
ver[++tot] = y;
edge[tot] = z;
Next[tot] = head[x];
head[x] = tot;
}
void dfs(int x)
{
for(int i = head[x];i;i = Next[i])
{
int y = ver[i];
int z = edge[i];
if(v[y]) continue;
v[y] = 1;
d[y] = d[x] + z;
dfs(y);
}
}
int main()
{
int x,y,z;
cin >> n >> m;
for(int i = 1;i <= m;i ++ )
{
cin >> x >> y >> z;
add(x,y,z);
add(y,x,z);
}
dfs(1);
for(int i = 1;i <= n;i ++ )
{
if(d[i] > ans) ans = d[i],farp;
d[i] = v[i] = 0;
}
ans = 0;
dfs(farp);
for(int i = 1;i <= n;i ++ )
{
if(d[i] > ans) ans = d[i];
}
cout << ans << endl;
return 0;
}
至于为什么不学树形DP的方法,因为树形DP无法记录最长链经过的结点,时间复杂度上又不比DFS好多少,所以不介绍了(其实还是因为太弱没看懂