結果

問題 No.922 東北きりきざむたん
ユーザー koi_kotyakoi_kotya
提出日時 2019-11-09 01:28:36
言語 C++14
(gcc 13.2.0 + boost 1.83.0)
結果
AC  
実行時間 304 ms / 2,000 ms
コード長 3,812 bytes
コンパイル時間 1,880 ms
コンパイル使用メモリ 176,252 KB
実行使用メモリ 31,840 KB
最終ジャッジ日時 2023-10-13 06:30:39
合計ジャッジ時間 6,964 ms
ジャッジサーバーID
(参考情報)
judge14 / judge12
このコードへのチャレンジ
(要ログイン)

テストケース

テストケース表示
入力 結果 実行時間
実行使用メモリ
testcase_00 AC 6 ms
9,156 KB
testcase_01 AC 6 ms
9,224 KB
testcase_02 AC 5 ms
9,288 KB
testcase_03 AC 6 ms
9,468 KB
testcase_04 AC 6 ms
9,332 KB
testcase_05 AC 6 ms
9,212 KB
testcase_06 AC 6 ms
9,084 KB
testcase_07 AC 7 ms
9,224 KB
testcase_08 AC 7 ms
9,392 KB
testcase_09 AC 68 ms
12,276 KB
testcase_10 AC 54 ms
10,940 KB
testcase_11 AC 69 ms
11,968 KB
testcase_12 AC 22 ms
10,428 KB
testcase_13 AC 22 ms
9,996 KB
testcase_14 AC 99 ms
13,432 KB
testcase_15 AC 13 ms
9,924 KB
testcase_16 AC 216 ms
17,832 KB
testcase_17 AC 215 ms
18,148 KB
testcase_18 AC 209 ms
17,852 KB
testcase_19 AC 218 ms
17,820 KB
testcase_20 AC 211 ms
17,708 KB
testcase_21 AC 280 ms
22,332 KB
testcase_22 AC 275 ms
22,268 KB
testcase_23 AC 260 ms
19,680 KB
testcase_24 AC 267 ms
19,764 KB
testcase_25 AC 198 ms
17,956 KB
testcase_26 AC 194 ms
17,976 KB
testcase_27 AC 192 ms
17,760 KB
testcase_28 AC 64 ms
11,028 KB
testcase_29 AC 304 ms
31,840 KB
権限があれば一括ダウンロードができます

ソースコード

diff #

#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> P;
int const INF = 1<<30;

#define p_ary(ary,a,b) do { cout << "["; for (int count = (a);count < (b);++count) cout << ary[count] << ((b)-1 == count ? "" : ", "); cout << "]\n"; } while(0)
#define p_map(map,it) do {cout << "{";for (auto (it) = map.begin();;++(it)) {if ((it) == map.end()) {cout << "}\n";break;}else cout << "" << (it)->first << "=>" << (it)->second << ", ";}}while(0)

int MAX_N = 100010;
vector<int> depth(MAX_N,0),dist(MAX_N,0);
vector<vector<int>> edges(MAX_N),anc(MAX_N);
vector<int> cnt(MAX_N,0);
vector<bool> used(MAX_N,false);
vector<int> child_sum(MAX_N,0);

void dfs(int i,int p = -1) {
    for (int j : edges[i]) if (j != p) {
        anc[j].push_back(i);
        depth[j] = depth[i]+1;
        dist[j] = dist[i]+1;
        dfs(j,i);
    }
}

void init(int k) {
    depth[k] = 0;
    dist[k] = 0;
    dfs(k);
    int n = anc.size();

}

int lca(int i,int j) {
    if (depth[i] > depth[j]) swap(i,j);
    while (depth[i] < depth[j]) {
        for (int k = anc[j].size()-1;k >= 0;--k) if (depth[anc[j][k]] >= depth[i]) {
            j = anc[j][k];
            break;
        }
    }
    while (i != j) {
        for (int k = anc[i].size()-1;k >= 0;--k) {
            if (anc[i][k] != anc[j][k]) {
                i = anc[i][k];
                j = anc[j][k];
                break;
            } else if (k == 0) {
                i = j = anc[i][0];
            }
        }
    }
    return i;
}

int calc_dist(int i,int j) {
    return dist[i]+dist[j]-dist[lca(i,j)]*2;
}

struct UnionFind {
private:
    vector<int> par,depth;
public:
    UnionFind (int n) {
        par.resize(n);
        depth = vector<int>(n,0);
        for (int i = 0;i < n;++i) par[i] = i;
    }

    int find(int x) {
        if (par[x] == x) return x;
        else return par[x] = find(par[x]);
    }

    void unite(int x,int y) {
        x = find(x);
        y = find(y);
        if (x == y) return;
        if (depth[x] < depth[y]) par[x] = y;
        else {
            par[y] = x;
            if (depth[x] == depth[y]) depth[x]++;
        }
    }

    bool same(int x,int y) {
        return find(x) == find(y);
    }
};

void dfs1(ll& s,int i,int p = -1) {
    child_sum[i] = cnt[i];
    s += (ll)cnt[i]*dist[i];
    for (int& j : edges[i]) if (j != p) {
        dfs1(s,j,i);
        child_sum[i] += child_sum[j];
    }
}

void dfs2(ll& sum,ll& mn,ll po,int i,int p = -1) {
    used[i] = true;
    mn = min(mn,sum);
    for (int& j : edges[i]) if (j != p) {
        sum += po-2*child_sum[j];
        dfs2(sum,mn,po,j,i);
        sum -= po-2*child_sum[j];
    }
}

int main() {
    int n,m,q;
    cin >> n >> m >> q;
    UnionFind uf(n);
    vector<P> qry(q);
    for (int i = 0;i < m;++i) {
        int u,v;
        cin >> u >> v;
        u--;v--;
        edges[u].push_back(v);
        edges[v].push_back(u);
        uf.unite(u,v);
    }
    for (int i = 0;i < q;++i) cin >> qry[i].first >> qry[i].second;
    ll ans = 0;
    for (int i = 0;i < n;++i) if (dist[i] == 0) init(i);
    for (int i = 0;i < 20;++i) {
        for (int j = 0;j < n;++j) {
            if (anc[j].size() < i+1 || anc[anc[j][i]].size() < i+1) continue;
            anc[j].push_back(anc[anc[j][i]][i]);
        }
    }
    for (P& p : qry) {
        int i = p.first-1,j = p.second-1;
        if (uf.same(i,j)) ans += calc_dist(i,j);
        else {
            cnt[i]++;
            cnt[j]++;
        }
    }
    for (int i = 0;i < n;++i) if (!used[i]) {
        ll sum = 0;
        dfs1(sum,i);
        ll mn = sum;
        ll po = child_sum[i];
        dfs2(sum,mn,po,i);
        ans += mn;
    }
    // for (int i = 0;i < n;++i) p_ary(anc[i],0,anc[i].size());
    // p_ary(dist,0,n);p_ary(depth,0,n);
    cout << ans << endl;
    return 0;
}
0