firiexp's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View the Project on GitHub firiexp/library

:heavy_check_mark: 木の直径(重み付き)
(tree/diameter_weighted.cpp)

説明

重み付き木の直径長とその両端点を $O(N)$ で求める。

できること

使い方

隣接リストを vector<vector<pair<int, T>>> で持ち、tree_diameter_weighted(g) を呼ぶ。

vector<vector<pair<int, long long>>> g(n);
g[u].push_back({v, w});
g[v].push_back({u, w});

auto [dist, ends] = tree_diameter_weighted(g);
int s = ends.first;
int t = ends.second;

重みなし木には diameter.cpptree_diameter を使う。

実装上の補足

任意の頂点から最遠点 s を取り、さらに s から最遠点を取る 2 回 DFS で求める。 木を仮定しているので、連結で閉路のないグラフに対して使う。

Verified with

Code

template<class T>
pair<T, pair<int, int>> tree_diameter_weighted(const vector<vector<pair<int, T>>> &G) {
    int n = G.size();
    if (n == 0) return {T(), {-1, -1}};

    vector<T> dist(n);
    int far = 0;
    auto dfs = [&](int v, int p, auto &&f) -> void {
        for (auto &&e : G[v]) {
            int to = e.first;
            T cost = e.second;
            if (to == p) continue;
            dist[to] = dist[v] + cost;
            if (dist[far] < dist[to]) far = to;
            f(to, v, f);
        }
    };

    dist[0] = T();
    dfs(0, -1, dfs);
    int s = far;
    dist[s] = T();
    dfs(s, -1, dfs);
    return {dist[far], {s, far}};
}

/**
 * @brief 木の直径(重み付き)
 */
#line 1 "tree/diameter_weighted.cpp"
template<class T>
pair<T, pair<int, int>> tree_diameter_weighted(const vector<vector<pair<int, T>>> &G) {
    int n = G.size();
    if (n == 0) return {T(), {-1, -1}};

    vector<T> dist(n);
    int far = 0;
    auto dfs = [&](int v, int p, auto &&f) -> void {
        for (auto &&e : G[v]) {
            int to = e.first;
            T cost = e.second;
            if (to == p) continue;
            dist[to] = dist[v] + cost;
            if (dist[far] < dist[to]) far = to;
            f(to, v, f);
        }
    };

    dist[0] = T();
    dfs(0, -1, dfs);
    int s = far;
    dist[s] = T();
    dfs(s, -1, dfs);
    return {dist[far], {s, far}};
}

/**
 * @brief 木の直径(重み付き)
 */
Back to top page