結果
問題 | No.922 東北きりきざむたん |
ユーザー | kcvlex |
提出日時 | 2019-11-09 02:51:40 |
言語 | C++14 (gcc 12.3.0 + boost 1.83.0) |
結果 |
WA
|
実行時間 | - |
コード長 | 5,646 bytes |
コンパイル時間 | 2,400 ms |
コンパイル使用メモリ | 187,348 KB |
実行使用メモリ | 42,368 KB |
最終ジャッジ日時 | 2024-09-15 03:53:53 |
合計ジャッジ時間 | 6,574 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge2 |
(要ログイン)
テストケース
テストケース表示入力 | 結果 | 実行時間 実行使用メモリ |
---|---|---|
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 | WA | - |
testcase_06 | WA | - |
testcase_07 | AC | 2 ms
5,376 KB |
testcase_08 | WA | - |
testcase_09 | WA | - |
testcase_10 | WA | - |
testcase_11 | WA | - |
testcase_12 | WA | - |
testcase_13 | WA | - |
testcase_14 | WA | - |
testcase_15 | AC | 42 ms
25,216 KB |
testcase_16 | WA | - |
testcase_17 | WA | - |
testcase_18 | WA | - |
testcase_19 | WA | - |
testcase_20 | WA | - |
testcase_21 | AC | 181 ms
33,408 KB |
testcase_22 | AC | 179 ms
33,280 KB |
testcase_23 | WA | - |
testcase_24 | WA | - |
testcase_25 | AC | 153 ms
34,304 KB |
testcase_26 | WA | - |
testcase_27 | AC | 165 ms
34,304 KB |
testcase_28 | AC | 70 ms
29,824 KB |
testcase_29 | AC | 188 ms
42,368 KB |
ソースコード
// #define DEBUGGING #include <bits/stdc++.h> using namespace std; #define endl '\n' #define ALL(V) (V).begin(), (V).end() #define ALLR(V) (V).rbegin(), (V).rend() template <typename T> using V = std::vector<T>; template <typename T> using VV = V<V<T>>; using ll = std::int64_t; using ull = std::uint64_t; using PLL = std::pair<ll, ll>; using TLL = std::tuple<ll, ll, ll>; template <typename T> const T& var_min(const T &t) { return t; } template <typename T> const T& var_max(const T &t) { return t; } template <typename T, typename... Tail> const T& var_min(const T &t, const Tail&... tail) { return std::min(t, var_min(tail...)); } template <typename T, typename... Tail> const T& var_max(const T &t, const Tail&... tail) { return std::max(t, var_max(tail...)); } template <typename T, typename... Tail> void chmin(T &t, const Tail&... tail) { t = var_min(t, tail...); } template <typename T, typename... Tail> void chmax(T &t, const Tail&... tail) { t = var_max(t, tail...); } template <typename T> const T& clamp(const T &t, const T &low, const T &high) { return std::max(low, std::min(high, t)); } template <typename T> void chclamp(T &t, const T &low, const T &high) { return t = clamp(t, low, high); } namespace init__ { struct InitIO { InitIO() { std::cin.tie(nullptr); std::ios_base::sync_with_stdio(false); std::cout << std::fixed << std::setprecision(30); } } init_io; } #define mv_rec make_v(init, tail...) template <typename T> T make_v(T init) { return init; } template <typename T, typename... Tail> auto make_v(T init, size_t s, Tail... tail) { return V<decltype(mv_rec)>(s, mv_rec); } #undef mv_rec #ifdef DEBUGGING #include "../../debug/debug.cpp" #else #define DEBUG(...) 0 #define DEBUG_SEPARATOR_LINE 0 #endif ll N; VV<ll> edges; V<ll> cnt_from; V<ll> prop_val; PLL dfs1(ll cur, ll pre, ll prop, ll add_v) { ll add_sum = 0; add_v += cnt_from[cur]; for(ll nxt : edges[cur]) if(nxt != pre) { ll a, b; tie(a, b) = dfs1(nxt, cur, prop + add_v, add_v); prop_val[cur] += a + b; add_sum += b; } ll fst = prop_val[cur]; ll snd = add_sum + cnt_from[cur]; prop_val[cur] += prop; return PLL(fst, snd); } ll dfs2(ll cur, ll pre, ll prop, ll add_v) { prop += add_v; ll ret = prop_val[cur] + prop; for(ll nxt : edges[cur]) if(nxt != pre) chmin(ret, dfs2(nxt, cur, prop, add_v)); return ret; } ll calc_from_root(ll root) { V<PLL> ret_lis(edges[root].size()); ll add_sum = 0; for(ll i = 0; i < edges[root].size(); i++) { ll a, b; tie(a, b) = dfs1(edges[root][i], root, cnt_from[root], cnt_from[root]); ret_lis[i] = PLL(a + b, b); prop_val[root] += a + b; add_sum += b; } ll ret = prop_val[root]; for(ll i = 0; i < edges[root].size(); i++) { ll prop = prop_val[root] - ret_lis[i].first; ll add_v = add_sum - ret_lis[i].second; chmin(ret, dfs2(edges[root][i], root, prop, add_v)); } return ret; } struct UnionFind { V<ll> parents, rank; UnionFind(ll N) : parents(N), rank(N, 1) { iota(ALL(parents), 0ll); } ll find(ll x) { return parents[x] == x ? x : parents[x] = find(parents[x]); } void unit(ll x, ll y) { ll px = find(x); ll py = find(y); if(px == py) return; if(rank[px] < rank[py]) swap(px, py); rank[px] += rank[px] == rank[py]; parents[py] = px; } bool is_same(ll x, ll y) { return find(x) == find(y); } }; struct LCA { V<ll> depth; VV<ll> dp; LCA(const VV<ll> &edges, const V<ll> &roots) : depth(edges.size()), dp(make_v<ll>(0, edges.size(), 20)) { for(ll root : roots) dfs(root, -1, edges); for(ll k = 1; k < 20; k++) for(ll i = 0; i < edges.size(); i++) { ll p = dp[i][k - 1]; if(p == -1) continue; dp[i][k] = dp[p][k - 1]; } } void dfs(ll cur, ll pre, const VV<ll> &edges, ll d = 0) { dp[cur][0] = pre; depth[cur] = d; for(ll nxt : edges[cur]) if(nxt != pre) dfs(nxt, cur, edges, d + 1); } ll get_par(ll x, ll dist) { ll cur = x; for(ll k = 0; k < 20 && cur != -1; k++) if((dist >> k) & 1) cur = dp[cur][k]; return cur; } ll get_lca(ll x, ll y) { if(depth[y] < depth[x]) swap(x, y); if(get_par(y, depth[y] - depth[x]) == x) return x; ll ok = 0, ng = max(depth[x], depth[y]); while(ng - ok > 1) { ll mid = (ok + ng) / 2; (get_par(x, mid) == get_par(y, mid) ? ok : ng) = mid; } return get_par(x, depth[x] - ok); } ll get_dist(ll x, ll y) { ll lca = get_lca(x, y); return (depth[x] - depth[lca]) + (depth[y] - depth[lca]); } }; int main() { ll N, M, Q; cin >> N >> M >> Q; edges.resize(N); cnt_from.resize(N); prop_val.resize(N); UnionFind uf(N); while(M--) { ll u, v; cin >> u >> v; u--; v--; edges[u].push_back(v); edges[v].push_back(u); uf.unit(u, v); } V<ll> plis(N); for(ll i = 0; i < N; i++) plis[i] = uf.find(i); sort(ALL(plis)); auto ite = unique(ALL(plis)); plis.erase(ite, plis.end()); LCA lca(edges, plis); ll ans = 0; while(Q--) { ll a, b; cin >> a >> b; a--; b--; if(uf.is_same(a, b)) { ans += lca.get_dist(a, b); } else { cnt_from[a]++; cnt_from[b]++; } } DEBUG(cnt_from); for(ll root : plis) ans += calc_from_root(root); cout << ans << endl; return 0; }