結果
問題 | No.922 東北きりきざむたん |
ユーザー | a |
提出日時 | 2019-11-09 01:52:42 |
言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 5,805 bytes |
コンパイル時間 | 2,435 ms |
コンパイル使用メモリ | 194,736 KB |
実行使用メモリ | 65,932 KB |
最終ジャッジ日時 | 2024-09-15 03:48:55 |
合計ジャッジ時間 | 9,115 ms |
ジャッジサーバーID (参考情報) |
judge4 / judge6 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
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 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | AC | 39 ms
22,972 KB |
testcase_13 | AC | 23 ms
8,576 KB |
testcase_14 | WA | - |
testcase_15 | AC | 27 ms
24,152 KB |
testcase_16 | WA | - |
testcase_17 | WA | - |
testcase_18 | WA | - |
testcase_19 | WA | - |
testcase_20 | WA | - |
testcase_21 | WA | - |
testcase_22 | WA | - |
testcase_23 | WA | - |
testcase_24 | AC | 378 ms
47,076 KB |
testcase_25 | AC | 341 ms
48,084 KB |
testcase_26 | AC | 344 ms
48,208 KB |
testcase_27 | AC | 337 ms
48,172 KB |
testcase_28 | AC | 90 ms
28,204 KB |
testcase_29 | AC | 358 ms
65,932 KB |
ソースコード
//#define _GLIBCXX_DEBUG #include "bits/stdc++.h" using namespace std; //------------------------------- Libraries --------------------------------// class UnionFind { vector<int> par; public: UnionFind(int n) : par(n, -1) {} int root(int x) { if (par[x] < 0) return x; else return par[x] = root(par[x]); } inline bool same(int u, int v) { return root(u) == root(v); } bool merge(int x, int y) { x = root(x); y = root(y); if (x == y) return false; if (par[x] > par[y]) swap(x, y); par[x] += par[y]; par[y] = x; return true; } int size(int x) { return -par[root(x)]; } }; class LowestCommonAncestor { //2^k >= n int n, k; vector<vector<int>> g, par; vector<int> dis; inline void build() { this->calc(); this->setpar(); } void calc(int v = 0, int p = -1) { this->par[0][v] = p; for (int nv : this->g[v]) { if (nv != p) { this->dis[nv] = this->dis[v] + 1; this->calc(nv, v); } } } void setpar() { for (int i = 0; i < this->k; i++) { for (int v = 0; v < this->n; v++) { if (this->par[i][v] != -1) { this->par[i + 1][v] = this->par[i][par[i][v]]; } } } } public: LowestCommonAncestor(int n_, vector<vector<int>> &g_) : n(n_), g(g_) { k = log2(n + 1); this->par.resize(k + 1, vector<int>(n, -1)); dis.resize(n); this->build(); } int get(int u, int v) { //dis[u] <= dis[v] if (this->dis[u] > this->dis[v]) { swap(u, v); } int d = this->dis[v] - this->dis[u]; for (int i = k; i >= 0; i--) { if (d >> i & 1) { v = this->par[i][v]; } } if (u == v) { return v; } for (int i = k; i >= 0; i--) { if (this->par[i][u] != this->par[i][v]) { u = this->par[i][u]; v = this->par[i][v]; } } return this->par[0][v]; } int dist(int u, int v) { return this->dis[u] + this->dis[v] - 2 * dis[this->get(u, v)]; } }; //verified @ https://onlinejudge.u-aizu.ac.jp/status/users/sifi_border/submissions/1/GRL_5_C/judge/3883181/C++14 //verified @ https://atcoder.jp/contests/abc014/submissions/7617701 //------------------------------- Type Names -------------------------------// using i64 = int_fast64_t; using seika = string; //akari : 1D, yukari : 2D, maki : 3D vector template <class kizuna> using akari = vector<kizuna>; template <class yuzuki> using yukari = akari<akari<yuzuki>>; template <class tsurumaki> using maki = akari<yukari<tsurumaki>>; //akane : ascending order, aoi : decending order template <class kotonoha> using akane = priority_queue<kotonoha, akari<kotonoha>, greater<kotonoha>>; template <class kotonoha> using aoi = priority_queue<kotonoha>; //------------------------------- Dubug Functions ---------------------------// inline void print() { cout << endl; } template <typename First, typename... Rest> void print(const First &first, const Rest &... rest) { cout << first << ' '; print(rest...); } //------------------------------- Solver ------------------------------------// void solve() { int n, m, q; cin >> n >> m >> q; yukari<int> g(n); UnionFind uf(n); for (int i = 0; i < m; i++) { int u, v; cin >> u >> v; u--, v--; g[u].push_back(v); g[v].push_back(u); uf.merge(u, v); } LowestCommonAncestor lca(n, g); akari<i64> ws(n); i64 ans = 0; for (int i = 0; i < q; i++) { int a, b; cin >> a >> b; a--, b--; if (uf.same(a, b)) { ans += lca.dist(a, b); } else { ws[a]++; ws[b]++; } } akari<map<int, pair<i64, i64>>> dp(n); auto calc = [&](auto &&calc, int v, int p, bool flag) -> pair<i64, i64> { if (dp[v].count(p)) { return dp[v][p]; } //res = {val, dif} pair<i64, i64> res = make_pair(0, ws[v]); if (flag || p == -1) { for (auto nv : g[v]) { if (nv == p) { continue; } auto chi = calc(calc, nv, v, flag); res.first += chi.first + chi.second; res.second += chi.second; } } else { auto par = calc(calc, p, v, 0); auto ard = calc(calc, v, -1, 0); res.first = ard.first - par.first - par.second; res.second = ard.second - par.second; } return dp[v][p] = res; }; akari<int> used(n); //uf の代表に対して呼ぶ for (int v = 0; v < n; v++) { int p = uf.root(v); if (used[p]) { continue; } used[p] = 1; calc(calc, p, -1, 1); } akari<i64> sum(n, 1e15); for (int v = 0; v < n; v++) { sum[uf.root(v)] = min(sum[uf.root(v)], calc(calc, v, -1, 0).first); //print(v, calc(calc, v, -1, 0).first, calc(calc, v, -1, 0).second); } for (int v = 0; v < n; v++) { if (!used[v]) { continue; } ans += sum[v]; } cout << ans << endl; } int main() { solve(); return 0; }