結果
| 問題 |
No.922 東北きりきざむたん
|
| コンテスト | |
| ユーザー |
ferin
|
| 提出日時 | 2019-11-08 22:43:45 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
WA
|
| 実行時間 | - |
| コード長 | 4,536 bytes |
| コンパイル時間 | 2,337 ms |
| コンパイル使用メモリ | 195,816 KB |
| 実行使用メモリ | 37,456 KB |
| 最終ジャッジ日時 | 2024-09-15 01:55:15 |
| 合計ジャッジ時間 | 9,782 ms |
|
ジャッジサーバーID (参考情報) |
judge1 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 21 WA * 4 TLE * 1 |
ソースコード
#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<int>> 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() {
dfs(/*root=*/0, -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);
if(sum == 0) continue;
centroid.clear();
dfs(i, -1);
graph.add_edge(n, i);
cs[uf.find(centroid[0])] = centroid[0];
}
dump(cs);
graph.build();
REP(i, q) {
if(uf.same(a[i], b[i])) {
ll lca = graph.get(a[i], b[i]);
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;
}
ferin