結果

問題 No.3463 Beltway
コンテスト
ユーザー wasd314
提出日時 2026-02-28 15:30:30
言語 C++23
(gcc 15.2.0 + boost 1.89.0)
コンパイル:
g++-15 -O2 -lm -std=c++23 -Wuninitialized -DONLINE_JUDGE -o a.out _filename_
実行:
./a.out
結果
RE  
実行時間 -
コード長 4,111 bytes
記録
記録タグの例:
初AC ショートコード 純ショートコード 純主流ショートコード 最速実行時間
コンパイル時間 2,699 ms
コンパイル使用メモリ 210,656 KB
実行使用メモリ 53,308 KB
最終ジャッジ日時 2026-02-28 15:53:29
合計ジャッジ時間 7,067 ms
ジャッジサーバーID
(参考情報)
judge1 / judge4
このコードへのチャレンジ
(要ログイン)
ファイルパターン 結果
sample AC * 1
other AC * 6 WA * 2 RE * 9
権限があれば一括ダウンロードができます

ソースコード

diff #
raw source code

#include <iostream>
#include <queue>
#include <utility>
#include <vector>

/* LCA(G, root): 木 G に対する根を root として Lowest Common Ancestor
を求める構造体 query(u,v): u と v の LCA を求める。計算量 O(logn) 前処理:
O(nlogn)時間, O(nlogn)空間
*/
struct LCA {
    using Graph = std::vector<std::vector<int>>;
    std::vector<std::vector<int>> parent;  // parent[k][u]:= u の 2^k 先の親
    std::vector<int> dist;  // root からの距離
    LCA(const Graph &G, int root = 0) { init(G, root); }

    // 初期化
    void init(const Graph &G, int root = 0) {
        int V = G.size();
        int K = 1;
        while ((1 << K) < V) K++;
        parent.assign(K, std::vector<int>(V, -1));
        dist.assign(V, -1);
        dfs(G, root, -1, 0);
        for (int k = 0; k + 1 < K; k++) {
            for (int v = 0; v < V; v++) {
                if (parent[k][v] < 0) {
                    parent[k + 1][v] = -1;
                } else {
                    parent[k + 1][v] = parent[k][parent[k][v]];
                }
            }
        }
    }

    // 根からの距離と1つ先の頂点を求める
    void dfs(const Graph &G, int v, int p, int d) {
        parent[0][v] = p;
        dist[v] = d;
        for (auto e : G[v]) {
            if (e != p) dfs(G, e, v, d + 1);
        }
    }

    int query(int u, int v) {
        if (dist[u] < dist[v]) std::swap(u, v);  // u の方が深いとする
        int K = parent.size();
        // LCA までの距離を同じにする
        for (int k = 0; k < K; k++) {
            if ((dist[u] - dist[v]) >> k & 1) {
                u = parent[k][u];
            }
        }
        // 二分探索で LCA を求める
        if (u == v) return u;
        for (int k = K - 1; k >= 0; k--) {
            if (parent[k][u] != parent[k][v]) {
                u = parent[k][u];
                v = parent[k][v];
            }
        }
        return parent[0][u];
    }
    int operator()(int x, int y) { return query(x, y); }
};
int solve() {
    using namespace std;
    int n, m, sv, gv;
    cin >> n >> m >> sv >> gv;
    sv--;
    gv--;
    using P = pair<int, int>;
    vector<P> edges(m);
    for (auto &e : edges) cin >> e.first >> e.second, e.first--, e.second--;
    const int oo = 1001001001;
    vector g1(n, vector<P>());
    vector g2(n, vector<int>());
    for (int i : views::iota(0, n)) {
        auto [x, y] = edges[i];
        g1[x].emplace_back(y, i);
        g1[y].emplace_back(x, i);
    }
    queue<int> q1;
    q1.push(sv);
    vector dist(n, oo);
    dist[sv] = 0;
    vector par(n, -1);
    vector pari(n, -1);
    while (!q1.empty()) {
        int v = q1.front();
        q1.pop();
        int nd = dist[v] + 1;
        for (auto [nv, i] : g1[v]) {
            if (dist[nv] > nd) {
                dist[nv] = nd;
                par[nv] = v;
                pari[nv] = i;
                g2[v].push_back(nv);
                g2[nv].push_back(v);
                q1.push(nv);
            }
        }
    }
    if (dist[gv] > oo / 2) {
        return -1;
    }
    LCA lca(g2, sv);
    vector<int> cy(n);
    vector mcy(m, 0);
    for (int i : views::iota(0, m)) {
        auto [x, y] = edges[i];
        if (pari[x] == i || pari[y] == i) continue;
        int l = lca(x, y);
        cy[x]++;
        cy[y]++;
        cy[l] -= 2;
        mcy[i] = 1;
    }
    auto dfs = [&](this auto self, int v, int p = -1) -> void {
        for (int nv : g2[v]) {
            if (nv == p) continue;
            self(nv, v);
            cy[v] += cy[nv];
        }
    };
    dfs(sv);
    for (int v : views::iota(0, n)) {
        if (v == sv) continue;
        mcy[pari[v]] = cy[v] >= 1;
    }
    vector dp(n, -oo);
    dp[sv] = 0;
    q1.push(sv);
    while (!q1.empty()) {
        int v = q1.front();
        q1.pop();
        for (auto [nv, i] : g1[v]) {
            if (dist[nv] != dist[v] + 1) continue;
            if (dp[nv] < 0) q1.push(nv);
            dp[nv] = max(dp[nv], dp[v] + mcy[i]);
        }
    }
    return dp[gv];
}
int main() {
    int ans = solve();
    std::cout << ans << "\n";
}
0