-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
156 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#pragma once | ||
|
||
#ifndef call_include | ||
#define call_include | ||
#include <bits/stdc++.h> | ||
using namespace std; | ||
#endif | ||
|
||
#include "../structure/2d_array.cpp" | ||
|
||
struct centroid_decomposition { | ||
private: | ||
int n; | ||
v2d<int> &E; | ||
vector<int> deleted; | ||
vector<int> subsizes; | ||
int found_cent; | ||
|
||
int centroid = -1; | ||
vector<pair<int, int>> subtrees; | ||
|
||
public: | ||
centroid_decomposition(v2d<int> &E) : E(E), n(E.size()), deleted(n, 0), subsizes(n){}; | ||
|
||
private: | ||
int dfs(int x, int tsize, int prev = -1) { | ||
if(found_cent) return -1; | ||
|
||
int size = 1, cent_flag = 1; | ||
for(int i = 0; i < E[x].size(); i++) { | ||
int nx = E[x][i]; | ||
if(deleted[nx] or nx == prev) continue; | ||
int chsize = dfs(nx, tsize, x); | ||
if(found_cent) return -1; | ||
if(chsize > tsize / 2) cent_flag = 0; | ||
size += chsize; | ||
} | ||
if(tsize - size > tsize / 2) cent_flag = 0; | ||
if(cent_flag) { | ||
found_cent = 1; | ||
centroid = x; | ||
for(int i = 0; i < E[x].size(); i++) { | ||
int nx = E[x][i]; | ||
if(deleted[nx]) continue; | ||
if(nx == prev) { | ||
subtrees.emplace_back(nx, tsize - size); | ||
} | ||
else { | ||
subtrees.emplace_back(nx, subsizes[nx]); | ||
} | ||
} | ||
} | ||
|
||
return subsizes[x] = size; | ||
} | ||
|
||
public: | ||
pair<int, vector<pair<int, int>>> get(int x, int tsize) { | ||
subtrees.clear(); | ||
found_cent = 0; | ||
dfs(x, tsize); | ||
return pair(centroid, subtrees); | ||
} | ||
|
||
inline void del(int x) { | ||
deleted[x] = 1; | ||
} | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
--- | ||
title: Centroid Decomposition (木の重心分解) | ||
documentation_of: ../centroid_decomposition.cpp | ||
--- | ||
|
||
## なにこれ | ||
木構造の重心を求める. | ||
|
||
## コンストラクタ | ||
- `centroid_decomposition(E)`:木または森を表す隣接リスト `E` について前処理を行う. | ||
|
||
## メンバ関数 | ||
- `get(x, tsize)`:頂点 `x` が含まれるサイズ `tsize` の木について,重心および重心分解後の各部分木に含まれる頂点とサイズの配列を返す. | ||
- `del(x)`:頂点 `x` を削除する. | ||
|
||
## 計算量 | ||
`E` に含まれる頂点数を $n$ とする. | ||
- コンストラクタ:$O(n)$ | ||
|
||
対象となる木のサイズを $m$ とする. | ||
- `get(x, tsize)`:$O(m)$ | ||
- `del(x)`:$O(1)$ | ||
|
||
## 備考 | ||
重心分解後の各部分木について,`get()` の返り値に含まれる頂点とサイズの情報を用いることで再帰的に重心分解を繰り返すことができる. | ||
|
||
1レイヤーの重心分解につき部分木の最大サイズは半分以下となるため,頂点数1の木になるまで重心分解したときのレイヤー数は $O(\log n)$ である. | ||
また,`del(x)` で重心を論理削除すれば `E` および `subsizes` を再初期化する必要はないため,1つのインスタンスを使い回すことができる. | ||
これは全体 $O(n \log n)$ で実行することができる. | ||
|
||
# 参考 | ||
- https://qiita.com/drken/items/4b4c3f1824339b090202 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
// competitive-verifier: PROBLEM https://codeforces.com/problemset/problem/321/C | ||
// competitive-verifier: IGNORE | ||
// non-supported site | ||
|
||
#ifndef call_include | ||
#define call_include | ||
#include <bits/stdc++.h> | ||
using namespace std; | ||
#endif | ||
|
||
#include "structure/2d_array.cpp" | ||
#include "graph/centroid_decomposition.cpp" | ||
|
||
int main() { | ||
int N; | ||
v2d<int> E; | ||
|
||
cin >> N; | ||
E.assign(N, 0); | ||
for(int i = 0; i < N - 1; i++) { | ||
int a, b; | ||
cin >> a >> b; | ||
a--, b--; | ||
E[a].emplace_back(b); | ||
E[b].emplace_back(a); | ||
} | ||
|
||
vector<char> ans(N); | ||
char c = 'A'; | ||
queue<int> q, qs; | ||
auto cd = centroid_decomposition(E); | ||
q.push(0); | ||
qs.push(N); | ||
while(not q.empty()) { | ||
queue<int> q2, qs2; | ||
while(not q.empty()) { | ||
int x = q.front(), xs = qs.front(); | ||
q.pop(), qs.pop(); | ||
|
||
auto res = cd.get(x, xs); | ||
int centroid = res.first; | ||
auto v = res.second; | ||
ans[centroid] = c; | ||
cd.del(centroid); | ||
for(int i = 0; i < v.size(); i++) { | ||
q2.push(v[i].first); | ||
qs2.push(v[i].second); | ||
} | ||
} | ||
swap(q, q2); | ||
swap(qs, qs2); | ||
c++; | ||
} | ||
|
||
for(int i = 0; i < N; i++) cout << ans[i] << (i < N - 1 ? ' ' : '\n'); | ||
} |