欢迎来踩本人博客
树的直径:
就是树上最长路
方法 :
求两边DFS即可
步骤:
1.从任意一点进行dfs,然后找到一个最长路径,记录最远点u
2.然后从u再进行dfs,找最长路径,记录一点v。
(u,v)就是树的直径
证明:可以看这个视频的第27:00(求树直径的原理和证明)
[video(video-iMl9BSet-1586583241905)(type-bilibili)(url-https://player.bilibili.com/player.html?aid=95472415)(image-https://ss.csdn.net/p?http://i0.hdslb.com/bfs/archive/5424cdb28ca513d905dc860808d8ea69fa389d1e.jpg)(title-第四届蓝桥杯a组)]
证明:
我们可以看出图中,树的直径是(4->2->5),长度为9.
我们一开始选定一个点dfs
如果是直径外一点,比如w1,从w1进行dfs找到的就是点4,路径就1->2->4,这个路径一定会与树的直径相交,而找到的4是直径的一端,那从4再进行dfs就是树的直径的另一端5,这样两遍dfs你就找到了树的直径
如果是直径内一点,比如w2,从w2开始dfs找到的最远点4,这个路径会被包含在树的直径里,那找到的点也就是树直径的一端,再dfs就可以找到另一端。
综上用两遍dfs就可以找到树的直径
代码:
网上找的模板:
#include <bits/stdc++.h>
using namespace std;
#define INF 10000000000
vector <int > G[1000005];
vector<int > E[1000005];
bool vis[1000005];
int d[1000005];
void init() {
memset(vis, 0, sizeof(vis));
}
void dfs(int u) {
vis[u] = 1;
int size = G[u].size(); //与顶点u相连的点数
for (int i = 0; i<size; i++) { //对与顶点u相连的点数进行扫描
int v = G[u][i];
if (!vis[v]) {
d[v] = d[u] + E[u][i];
dfs(v);
}
}
}
int main() {
int n;
cin >> n;
int u, v, w;
for (int i = 0; i<n-1; i++) { //建立树过程
scanf("%d%d%d",&u,&v,&w);
G[u-1].push_back(v-1); //顶点两边都要记录
E[u-1].push_back(w);
G[v-1].push_back(u-1);
E[v-1].push_back(w);
}
init();
for (int i = 0; i<n; i++) d[i] = (i == 0?0:INF);
dfs(0);
int start = 0;
int max = -1;
for (int i = 0; i<n; i++) {
if (d[i] > max && d[i] != INF) {
max = d[i];
start = i;
}
}
init();
for (int i = 0; i<n; i++) d[i] = (i == start?0:INF);
dfs(start);
int ans = -1;
for (int i = 0; i<n; i++) {
if (d[i] > ans && d[i] != INF) {
ans = d[i];
}
}
//ans = 10*ans + ans*(ans+1)/2;
cout << ans << endl; //ans 即为直径
return 0;
}


京公网安备 11010502036488号