学习树的直径前提须知
树的直径 是一棵树的某两个最深的叶子节点的连线,多用于与图论算法嵌套考
算法内容
竞赛需要用到的点
1、很简单的算法,不会单独考,学习和熟练使用它的多种情况
树的直径略讲
很简单,两次dfs
至于为什么,可以画图模拟一下,因为一次dfs必然会在一棵子树或者根节点上,每次dfs必然找到一棵子树的最深的叶子节点,那么第二次dfs必然找到另外一棵子树的叶子节点,这两点的唯一路径就是整棵树的直径。由这个定理我们又可以得到,树的直径不止一条。
代码如下(参考PT07Z - Longest path in a tree)
//#define fre yes
#include <cstdio>
#include <cstring>
const int N = 10005;
int head[N << 1], to[N << 1], ver[N << 1];
int d[N];
bool Vis[N];
int tot;
void addedge(int x, int y) {
ver[tot] = y;
to[tot] = head[x];
head[x] = tot++;
}
void dfs(int u) {
Vis[u] = true;
for (int i = head[u]; ~i; i = to[i]) {
int v = ver[i];
if(!Vis[v]) {
d[v] = d[u] + 1;
dfs(v);
}
}
}
int diameter(int n) {
int st = 1, mx = -1e9;
dfs(st);
for (int i = 1; i <= n; i++) {
if(d[i] > mx) {
mx = d[i];
st = i;
}
}
memset(d, 0, sizeof(d));
memset(Vis, false, sizeof(Vis));
dfs(st);
mx = -1e9;
for (int i = 1; i <= n; i++) {
if(d[i] > mx) {
mx = d[i];
}
} return mx;
}
int main() {
memset(head, -1, sizeof(head));
static int n;
scanf("%d", &n);
for (int i = 1; i < n; i++) {
int u, v;
scanf("%d %d", &u, &v);
addedge(u, v);
addedge(v, u);
}
printf("%d
",diameter(n));
return 0;
}
那么也就会存在另一个问题,让你输出你找的两个节点的最短路径
挺智障的问题,可以在更新完后得到两个节点来搞,也可以在更新时来搞 前者时间消耗多一点,后者空间消耗多一下 看自己喜好 这里就不放代码了