結果
| 問題 |
No.922 東北きりきざむたん
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2019-11-08 22:19:40 |
| 言語 | C++14 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
AC
|
| 実行時間 | 237 ms / 2,000 ms |
| コード長 | 4,657 bytes |
| コンパイル時間 | 2,386 ms |
| コンパイル使用メモリ | 189,920 KB |
| 実行使用メモリ | 36,660 KB |
| 最終ジャッジ日時 | 2024-09-15 01:35:27 |
| 合計ジャッジ時間 | 7,095 ms |
|
ジャッジサーバーID (参考情報) |
judge4 / judge2 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 4 |
| other | AC * 26 |
ソースコード
#include <bits/stdc++.h>
using namespace std;
struct UnionFind {
vector<int> par;
vector<int> sz;
UnionFind(int n=0){
if(n>0) initialize(n);
}
void initialize(int n){
par.resize(n);
sz.resize(n);
for(int i=0; i<n; i++){
par[i] = i;
sz[i] = 1;
}
}
int find(int x){
if(par[x] == x){
return x;
}else{
return par[x] = find(par[x]);
}
}
bool unite(int x, int y){
x = find(x);
y = find(y);
if(x == y) return false;
if(sz[x] > sz[y]) swap(x, y);
par[x] = y;
sz[y] += sz[x];
return true;
}
bool same(int x, int y){
return find(x) == find(y);
}
int size(int x){
return sz[find(x)];
}
};
struct LCA{
static const int BITLEN_MAX = 20;
vector<int> parent[BITLEN_MAX];
vector<int> depth;
int bitlen;
LCA(int N, vector<vector<int>>& edges){
int root = 0;
bitlen = 1;
while((1<<bitlen) < N) bitlen += 1;
for(int i=0; i<bitlen; i++) parent[i].resize(N);
depth.resize(N, -1);
dfs(root, -1, 0, edges);
for(int k=0; k<bitlen-1; k++){
for(int v=0; v<N; v++){
if(depth[v] == -1) continue;
if(parent[k][v] < 0){
parent[k+1][v] = -1;
}else{
parent[k+1][v] = parent[k][parent[k][v]];
}
}
}
}
void dfs(int v, int p, int d, vector<vector<int>>& edges){
parent[0][v] = p;
depth[v] = d;
for(auto u : edges[v]){
if(u != p) dfs(u, v, d+1, edges);
}
}
int calc_lca(int u, int v){
if(depth[u] > depth[v]) swap(u, v);
for(int k=0; k<bitlen; k++){
if( ((depth[v]-depth[u]) >> k) & 1 ) v = parent[k][v];
}
if(u == v) return u;
for(int k=bitlen-1; k>=0; k--){
if(parent[k][u] != parent[k][v]){
u = parent[k][u];
v = parent[k][v];
}
}
return parent[0][u];
}
int calc_dist(int u, int v){
int l = calc_lca(u, v);
return depth[u] + depth[v] - depth[l]*2;
}
};
vector<int64_t> dp, num;
void dfs(int i, int p, vector<int>& W, vector<vector<int>>& E){
num[i] = W[i];
for(int j : E[i]) if(j != p){
dfs(j, i, W, E);
num[i] += num[j];
dp[i] += dp[j] + num[j];
}
}
void dfs2(int i, int p, vector<int>& W, vector<vector<int>>& E, int64_t v, int n, int64_t& ans){
ans = min(ans, dp[i] + v);
for(int j : E[i]) if(j != p){
int n2 = num[i] - num[j] + n;
int64_t v2 = dp[i] - (dp[j] + num[j]) + v + n2;
dfs2(j, i, W, E, v2, n2, ans);
}
}
int64_t calc(vector<int>& W, vector<vector<int>>& E){
int sz = W.size();
dp = vector<int64_t>(sz);
num = vector<int64_t>(sz);
dfs(0, -1, W, E);
int64_t ans = 1e18;
dfs2(0, -1, W, E, 0, 0, ans);
// for(int a : W) cerr << a << " ";
// cerr << endl;
// cerr << ans << endl;
return ans;
}
int main(){
int N, M, Q;
cin >> N >> M >> Q;
vector<int> edges[100000];
UnionFind uf(N);
for(int i=0; i<M; i++){
int a, b;
cin >> a >> b;
a--; b--;
edges[a].push_back(b);
edges[b].push_back(a);
uf.unite(a, b);
}
vector<int> group(N, -1), pos(N);
vector<vector<int>> vs;
for(int i=0; i<N; i++){
int r = uf.find(i);
if(group[r] == -1){
group[r] = vs.size();
vs.push_back({});
}
group[i] = group[r];
pos[i] = vs[group[r]].size();
vs[group[i]].push_back(i);
}
int G = vs.size();
vector<int> sz(G);
vector<vector<int>> W(G);
vector<vector<vector<int>>> E(G);
vector<vector<pair<int, int>>> sames(G);
for(int i=0; i<G; i++){
sz[i] = vs[i].size();
W[i].resize(sz[i]);
E[i].resize(sz[i]);
}
for(int i=0; i<N; i++) for(int j : edges[i]) E[group[i]][pos[i]].push_back(pos[j]);
for(int i=0; i<Q; i++){
int a, b;
cin >> a >> b;
a--; b--;
if(uf.same(a, b)){
sames[group[a]].emplace_back(pos[a], pos[b]);
}else{
W[group[a]][pos[a]]++;
W[group[b]][pos[b]]++;
}
}
int64_t ans = 0;
for(int g=0; g<G; g++){
ans += calc(W[g], E[g]);
LCA lca(sz[g], E[g]);
for(auto& p : sames[g]) ans += lca.calc_dist(p.first, p.second);
}
cout << ans << endl;
return 0;
}