結果

問題 No.922 東北きりきざむたん
ユーザー ferinferin
提出日時 2019-11-08 22:53:44
言語 C++14
(gcc 12.3.0 + boost 1.83.0)
結果
AC  
実行時間 242 ms / 2,000 ms
コード長 4,596 bytes
コンパイル時間 2,489 ms
コンパイル使用メモリ 196,268 KB
実行使用メモリ 36,680 KB
最終ジャッジ日時 2024-09-15 02:02:34
合計ジャッジ時間 7,296 ms
ジャッジサーバーID
(参考情報)
judge3 / judge1
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 2 ms
5,248 KB
testcase_01 AC 2 ms
5,376 KB
testcase_02 AC 2 ms
5,376 KB
testcase_03 AC 2 ms
5,376 KB
testcase_04 AC 2 ms
5,376 KB
testcase_05 AC 2 ms
5,376 KB
testcase_06 AC 3 ms
5,376 KB
testcase_07 AC 3 ms
5,376 KB
testcase_08 AC 2 ms
5,376 KB
testcase_09 AC 80 ms
16,864 KB
testcase_10 AC 46 ms
7,680 KB
testcase_11 AC 69 ms
13,940 KB
testcase_12 AC 34 ms
17,828 KB
testcase_13 AC 24 ms
7,808 KB
testcase_14 AC 137 ms
25,696 KB
testcase_15 AC 23 ms
17,676 KB
testcase_16 AC 198 ms
25,932 KB
testcase_17 AC 192 ms
26,056 KB
testcase_18 AC 192 ms
26,060 KB
testcase_19 AC 194 ms
25,928 KB
testcase_20 AC 198 ms
25,936 KB
testcase_21 AC 242 ms
24,912 KB
testcase_22 AC 227 ms
24,908 KB
testcase_23 AC 182 ms
26,700 KB
testcase_24 AC 183 ms
26,700 KB
testcase_25 AC 138 ms
27,084 KB
testcase_26 AC 136 ms
26,956 KB
testcase_27 AC 135 ms
26,956 KB
testcase_28 AC 142 ms
27,504 KB
testcase_29 AC 144 ms
36,680 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<ll, ll>;
#define FOR(i, a, n) for (ll i = (ll)a; i < (ll)n; ++i)
#define REP(i, n) FOR(i, 0, n)
#define ALL(x) x.begin(), x.end()
template<typename T> void chmin(T &a, const T &b) { a = min(a, b); }
template<typename T> void chmax(T &a, const T &b) { a = max(a, b); }
struct FastIO {FastIO() { cin.tie(0); ios::sync_with_stdio(0); }}fastiofastio;
#ifdef DEBUG_ 
#include "../program_contest_library/memo/dump.hpp"
#else
#define dump(...)
#endif
const ll INF = 1LL<<60;

struct UnionFind {
    vector<int> par, s;
    UnionFind(int n=2e5) { init(n); }
    void init(int n) { 
        s.assign(n, 1); par.resize(n); 
        iota(par.begin(), par.end(), 0);
    }
    int find(int x) {
        if(par[x] == x) return x;
        return par[x] = find(par[x]);
    }
    void unite(int x, int y) {
        x = find(x);
        y = find(y);
        if(x == y) return;
        if(s[x] < s[y]) par[x] = y, s[y] = s[x] + s[y];
        else par[y] = x, s[x] = s[x] + s[y];
    }
    bool same(int x, int y) { return find(x) == find(y); }
    int size(int x) { return s[find(x)]; }
};

struct LCA {
    const int n = 0;
    const int log2_n = 0;
    vector<vector<ll>> g;
    vector<vector<int>> par;  // par[2^i上][頂点v]
    vector<int> dep;

    void dfs(int v, int p, int d) {
        par[0][v] = p;
        dep[v] = d;
        for(auto to: g[v]) {
            if(to == p) continue;
            dfs(to, v, d+1);
        }
    }

    LCA() {}
    LCA(int n) : n(n), log2_n(log2(n)+1), g(n),
        par(log2_n, vector<int>(n)), dep(n) {}

    void add_edge(int u, int v) {
        g[u].push_back(v);
        g[v].push_back(u);
    }

    void build(ll rt) {
        dump(g);
        dfs(rt, -1, 0);
        for(int i=0; i+1 < log2_n; ++i) {
            for(int j = 0; j < n; ++j) {
                if(par[i][j] < 0) par[i+1][j] = -1;
                else par[i+1][j] = par[i][par[i][j]];
            }
        }
    }

    int get(int u, int v) {
        if(dep[u] > dep[v]) swap(u, v);
        REP(i, log2_n) {
            if((dep[v] - dep[u]) >> i & 1) {
                v = par[i][v];
            }
        }
        if(u == v) return u;
        for(int i=log2_n-1; i>=0; --i) {
            if(par[i][u] != par[i][v]) {
                u = par[i][u];
                v = par[i][v];
            }
        }
        return par[0][u];
    }
};

int main(void) {
    ll n, m, q;
    cin >> n >> m >> q;
    vector<vector<ll>> g(n);
    UnionFind uf(n);
    LCA graph(n+1);
    REP(i, m) {
        ll u, v;
        cin >> u >> v;
        u--, v--;
        g[u].push_back(v);
        g[v].push_back(u);
        uf.unite(u, v);
        graph.add_edge(u, v);
    }
    vector<ll> a(q), b(q), sz(n);
    ll ret = 0;
    REP(i, q) {
        cin >> a[i] >> b[i];
        a[i]--, b[i]--;
        if(!uf.same(a[i], b[i])) sz[a[i]]++, sz[b[i]]++;
    }

    dump(g);
    dump(sz);

    ll sum = 0;
    function<void(ll,ll)> pre = [&](ll v, ll p) {
        sum += sz[v];
        for(auto to: g[v]) if(to != p) {
            pre(to, v);
        }
    };

    vector<bool> used(n);
    vector<ll> centroid;
    function<void(ll,ll)> dfs = [&](ll v, ll p) {
        // dump(v, p);
        used[v] = true;
        bool is_centroid = true;
        for(auto to : g[v]) if (to != p) {
            dfs(to, v);
            if(sz[to] > sum/2) is_centroid = false;
            sz[v] += sz[to];
            // dump(to, sz[v], is_centroid);
        }
        // dump(v, is_centroid, sz[v]);
        if(sum-sz[v] > sum/2) is_centroid = false;
        if(is_centroid) centroid.push_back(v);
    };

    map<ll, ll> cs; 
    REP(i, n) {
        if(used[i]) continue;
        sum = 0;
        pre(i, -1);
        centroid.clear();
        dfs(i, -1);
        graph.add_edge(n, i);
        if(sum > 0) cs[uf.find(centroid[0])] = centroid[0];
    }
    dump(cs);

    graph.build(n);
    dump(graph.dep);
    REP(i, q) {
        if(uf.same(a[i], b[i])) {
            ll lca = graph.get(a[i], b[i]);
            dump(a[i], b[i], lca);
            ret += graph.dep[a[i]] + graph.dep[b[i]] - 2 * graph.dep[lca];
        } else {
            ll u = a[i], v = cs[uf.find(a[i])], lca = graph.get(u, v);
            // dump(u, v, lca);
            ret += graph.dep[u] + graph.dep[v] - 2 * graph.dep[lca];
            u = b[i], v = cs[uf.find(b[i])], lca = graph.get(u, v); 
            // dump(u, v, lca);
            ret += graph.dep[u] + graph.dep[v] - 2 * graph.dep[lca];
        }
        dump(i, ret);
    }
    cout << ret << endl;

    return 0;
}
0