CppLibrary

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

View the Project on GitHub Tiramister/CppLibrary

:heavy_check_mark: Verify/centroid_decomposition_diameter.test.cpp

Depends on

Code

#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_5_A"

#include "../Graph/centroid_decomposition.hpp"

#include <iostream>
#include <algorithm>
#include <queue>
#include <tuple>

int main() {
    std::cin.tie();
    std::ios::sync_with_stdio(false);

    int n;
    std::cin >> n;

    Graph<int> graph(n);
    for (int i = 0; i < n - 1; ++i) {
        int u, v, w;
        std::cin >> u >> v >> w;
        graph.span(false, u, v, w);
    }

    Centroid<int> cent(graph);

    int ans = 0;
    std::queue<int> cents;
    cents.push(0);

    std::vector<int> dist(n);
    while (!cents.empty()) {
        int r = cents.front();
        cents.pop();
        r = cent.find(r);
        cent.deleted[r] = true;

        std::vector<int> fars({0, 0});
        for (auto e : graph[r]) {
            if (cent.deleted[e.dst]) continue;
            cents.push(e.dst);

            // BFS
            std::queue<std::pair<int, int>> que;
            que.emplace(e.dst, -1);
            dist[e.dst] = e.cost;

            int far = 0;
            while (!que.empty()) {
                int v, p;
                std::tie(v, p) = que.front();
                que.pop();
                far = std::max(far, dist[v]);

                for (auto f : graph[v]) {
                    if (f.dst == p || cent.deleted[f.dst]) continue;
                    dist[f.dst] = dist[v] + f.cost;
                    que.emplace(f.dst, v);
                }
            }
            fars.push_back(far);
        }

        std::sort(fars.rbegin(), fars.rend());
        if (fars.size() >= 2) ans = std::max(ans, fars[0] + fars[1]);
    }

    std::cout << ans << "\n";
    return 0;
}
#line 1 "Verify/centroid_decomposition_diameter.test.cpp"
#define PROBLEM "https://onlinejudge.u-aizu.ac.jp/courses/library/5/GRL/all/GRL_5_A"

#line 2 "Graph/centroid_decomposition.hpp"

#line 2 "Graph/graph.hpp"

#include <vector>

template <class Cost = int>
struct Edge {
    int src, dst;
    Cost cost;

    Edge() = default;
    Edge(int src, int dst, Cost cost = 1)
        : src(src), dst(dst), cost(cost){};

    bool operator<(const Edge<Cost>& e) const { return cost < e.cost; }
    bool operator>(const Edge<Cost>& e) const { return cost > e.cost; }
};

template <class Cost = int>
struct Graph : public std::vector<std::vector<Edge<Cost>>> {
    using std::vector<std::vector<Edge<Cost>>>::vector;

    void span(bool direct, int src, int dst, Cost cost = 1) {
        (*this)[src].emplace_back(src, dst, cost);
        if (!direct) (*this)[dst].emplace_back(dst, src, cost);
    }
};
#line 4 "Graph/centroid_decomposition.hpp"

template <class Cost = int>
struct Centroid {
    Graph<Cost> graph;
    std::vector<bool> deleted;
    std::vector<int> sz;

    explicit Centroid(const Graph<Cost>& graph)
        : graph(graph), deleted(graph.size(), false), sz(graph.size()) {}

    int szdfs(int v, int p = -1) {
        sz[v] = 1;
        for (auto e : graph[v]) {
            if (e.dst == p || deleted[e.dst]) continue;
            sz[v] += szdfs(e.dst, v);
        }
        return sz[v];
    }

    int find(int v) {
        int n = szdfs(v);

        int p = -1;
        while (true) {
            int nxt = -1;
            for (auto e : graph[v]) {
                if (e.dst == p || deleted[e.dst]) continue;
                if (nxt == -1 || sz[e.dst] > sz[nxt]) nxt = e.dst;
            }

            if (nxt == -1 || sz[nxt] <= n / 2) return v;
            p = v;
            v = nxt;
        }
    }
};
#line 4 "Verify/centroid_decomposition_diameter.test.cpp"

#include <iostream>
#include <algorithm>
#include <queue>
#include <tuple>

int main() {
    std::cin.tie();
    std::ios::sync_with_stdio(false);

    int n;
    std::cin >> n;

    Graph<int> graph(n);
    for (int i = 0; i < n - 1; ++i) {
        int u, v, w;
        std::cin >> u >> v >> w;
        graph.span(false, u, v, w);
    }

    Centroid<int> cent(graph);

    int ans = 0;
    std::queue<int> cents;
    cents.push(0);

    std::vector<int> dist(n);
    while (!cents.empty()) {
        int r = cents.front();
        cents.pop();
        r = cent.find(r);
        cent.deleted[r] = true;

        std::vector<int> fars({0, 0});
        for (auto e : graph[r]) {
            if (cent.deleted[e.dst]) continue;
            cents.push(e.dst);

            // BFS
            std::queue<std::pair<int, int>> que;
            que.emplace(e.dst, -1);
            dist[e.dst] = e.cost;

            int far = 0;
            while (!que.empty()) {
                int v, p;
                std::tie(v, p) = que.front();
                que.pop();
                far = std::max(far, dist[v]);

                for (auto f : graph[v]) {
                    if (f.dst == p || cent.deleted[f.dst]) continue;
                    dist[f.dst] = dist[v] + f.cost;
                    que.emplace(f.dst, v);
                }
            }
            fars.push_back(far);
        }

        std::sort(fars.rbegin(), fars.rend());
        if (fars.size() >= 2) ans = std::max(ans, fars[0] + fars[1]);
    }

    std::cout << ans << "\n";
    return 0;
}
Back to top page