Skip to content

Commit e8fec97

Browse files
hitonanodeweb-flow
andauthored
Tree Diameter (#39)
* Tree Diameter * [auto-verifier] verify commit 7231abe Co-authored-by: GitHub <noreply@github.com>
1 parent bc192fe commit e8fec97

File tree

4 files changed

+91
-0
lines changed

4 files changed

+91
-0
lines changed

.verify-helper/timestamps.remote.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@
133133
"string/test/sa_count_keyword.test.cpp": "2021-01-02 01:50:58 +0900",
134134
"string/test/suffix_array.test.cpp": "2021-01-02 00:51:41 +0900",
135135
"string/test/z_algorithm.test.cpp": "2021-01-01 16:52:32 +0900",
136+
"tree/test/diameter.test.cpp": "2021-06-09 00:24:00 +0900",
136137
"tree/test/frequency_table_of_tree_distance.test.cpp": "2021-06-06 15:23:40 +0900",
137138
"tree/test/hl_decomposition.test.cpp": "2021-06-06 15:23:40 +0900",
138139
"tree/test/lca.test.cpp": "2021-02-26 00:36:27 +0900",

tree/diameter.hpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#pragma once
2+
#include <algorithm>
3+
#include <cassert>
4+
#include <tuple>
5+
#include <utility>
6+
#include <vector>
7+
8+
// CUT begin
9+
// 木の直径と,これをなすパスの頂点を出力
10+
template <class Weight> struct TreeDiameter {
11+
int n;
12+
std::vector<std::vector<std::pair<int, Weight>>> to;
13+
std::vector<int> prev;
14+
std::vector<Weight> dist;
15+
TreeDiameter(int V) : n(V), to(V), prev(V), dist(V) {}
16+
void add_edge(int s, int t, Weight w) {
17+
assert(0 <= s and s < n);
18+
assert(0 <= t and t < n);
19+
to[s].emplace_back(t, w);
20+
to[t].emplace_back(s, w);
21+
}
22+
int argdmax;
23+
Weight dmax;
24+
void dfs(int now, int prv) {
25+
if (dmax < dist[now]) dmax = dist[now], argdmax = now;
26+
for (auto p : to[now]) {
27+
int nxt;
28+
Weight w;
29+
std::tie(nxt, w) = p;
30+
if (nxt == prv) continue;
31+
prev[nxt] = now;
32+
dist[nxt] = dist[now] + w;
33+
dfs(nxt, now);
34+
}
35+
}
36+
std::pair<Weight, std::vector<int>> get_diameter_edges(int root = 0) {
37+
prev[root] = -1;
38+
dist[root] = 0;
39+
dmax = 0, argdmax = root;
40+
dfs(root, -1);
41+
dmax = 0, prev[argdmax] = -1, dist[argdmax] = 0;
42+
dfs(argdmax, -1);
43+
std::vector<int> ret;
44+
while (argdmax >= 0) {
45+
ret.push_back(argdmax);
46+
argdmax = prev[argdmax];
47+
}
48+
return {dmax, ret};
49+
}
50+
};

tree/diameter.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
---
2+
title: Tree diameter (木の直径)
3+
documentation_of: ./diameter.hpp
4+
---
5+
6+
木の直径を計算.
7+
8+
## 使用方法
9+
10+
```cpp
11+
TreeDiameter<long long> tree(N);
12+
for (auto [s, t, w] : edges) tree.add_edge(s, t, w);
13+
14+
// 頂点 r を含む部分木に関して,直径 D とこれをなす頂点列 vs (の一つ)を計算
15+
auto [D, vs] = tree.get_diameter_edges(r);
16+
```
17+
18+
## 問題例
19+
20+
- [Library Checker: Tree Diameter](https://judge.yosupo.jp/problem/tree_diameter)

tree/test/diameter.test.cpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
#define PROBLEM "https://judge.yosupo.jp/problem/tree_diameter"
2+
#include "../diameter.hpp"
3+
#include <iostream>
4+
using namespace std;
5+
6+
int main() {
7+
cin.tie(nullptr), ios::sync_with_stdio(false);
8+
int N;
9+
cin >> N;
10+
TreeDiameter<long long> tree(N);
11+
for (int i = 0; i < N - 1; i++) {
12+
int a, b, c;
13+
cin >> a >> b >> c;
14+
tree.add_edge(a, b, c);
15+
}
16+
auto ret = tree.get_diameter_edges();
17+
cout << ret.first << ' ' << ret.second.size() << '\n';
18+
for (auto x : ret.second) cout << x << ' ';
19+
cout << '\n';
20+
}

0 commit comments

Comments
 (0)