树的直径求解
定义
树上任意两点最短路的最大值
方法一:两次DFS
条件:不能有负权边
第一次任一点出发找最短路的最大值点,必然是直径的一个端点
第二次dfs从那个端点找最大值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
| int n; vector<int> tree[N]; int d[N]; int cur; void dfs(int rt, int fa) { for (auto it : tree[rt]) { if (it == fa) continue; d[it] = d[rt] + 1; if (d[it] > d[cur]) cur = it; dfs(it, rt); } } int main() { read(n); int u, v; for (int i = 1; i < n; i++) { read(u), read(v); tree[u].push_back(v); tree[v].push_back(u); } d[1] = 0; dfs(1, -1); d[cur] = 0; dfs(cur, -1); printf("%d\n", d[cur]); return 0; }
|
方法二:树形dp
随便指定节点为根,dfs一个最远距离和次远距离,答案是所有节点最远+次远的最大值(代码道理更清楚)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| int n; vector<int> tree[N]; int d; int d1[N], d2[N]; void dfs(int rt, int fa) { d1[rt] = d2[rt] = 0; for (auto it : tree[rt]) { if (it == fa) continue; dfs(it, rt); int tmp = d1[it] + 1; if (tmp > d1[rt]) d2[rt] = d1[rt], d1[rt] = tmp; else if (tmp > d2[rt]) d2[rt] = tmp; } d = max(d, d1[rt] + d2[rt]); }
|