-
Notifications
You must be signed in to change notification settings - Fork 11
/
Copy pathdiameter.hpp
50 lines (49 loc) · 1.4 KB
/
diameter.hpp
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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#pragma once
#include <algorithm>
#include <cassert>
#include <tuple>
#include <utility>
#include <vector>
// CUT begin
// 木の直径と,これをなすパスの頂点を出力
template <class Weight> struct TreeDiameter {
int n;
std::vector<std::vector<std::pair<int, Weight>>> to;
std::vector<int> prev;
std::vector<Weight> dist;
TreeDiameter(int V) : n(V), to(V), prev(V), dist(V) {}
void add_edge(int s, int t, Weight w) {
assert(0 <= s and s < n);
assert(0 <= t and t < n);
to[s].emplace_back(t, w);
to[t].emplace_back(s, w);
}
int argdmax;
Weight dmax;
void dfs(int now, int prv) {
if (dmax < dist[now]) dmax = dist[now], argdmax = now;
for (auto p : to[now]) {
int nxt;
Weight w;
std::tie(nxt, w) = p;
if (nxt == prv) continue;
prev[nxt] = now;
dist[nxt] = dist[now] + w;
dfs(nxt, now);
}
}
std::pair<Weight, std::vector<int>> get_diameter_edges(int root = 0) {
prev[root] = -1;
dist[root] = 0;
dmax = 0, argdmax = root;
dfs(root, -1);
dmax = 0, prev[argdmax] = -1, dist[argdmax] = 0;
dfs(argdmax, -1);
std::vector<int> ret;
while (argdmax >= 0) {
ret.push_back(argdmax);
argdmax = prev[argdmax];
}
return {dmax, ret};
}
};