結果
| 問題 |
No.922 東北きりきざむたん
|
| コンテスト | |
| ユーザー |
kcvlex
|
| 提出日時 | 2019-11-09 02:51:40 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.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 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 9 WA * 17 |
ソースコード
// #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;
}
kcvlex