重心分解
(give_us_tmp/centroid_decomposition.cpp)
Code
/**
* @brief 重心分解
* 構築:O(NlogN)
* get_root() :出来上がった木の根を返す O(1)
* operator[](int i) :出来上がった木の子を返す
* get_euler_tour(int i):出来上がった木のdfs順を返す
*
* ・全てのパスについて調べる方法
* dfs順を取得してループを回し、
* パス上にあり、dfs順で最小となる頂点がiであるようなパスをなめていく
*
* verified with :https://judge.yosupo.jp/problem/frequency_table_of_tree_distance
* submission :https://judge.yosupo.jp/submission/28303
*/
class centroid_decomposition{
using graph=vector<vector<int>>;
graph g;
vector<int>used;
vector<int>v;
graph ch;
int s;
int dfs(int n,int p,int sz,int root){
if(used[n])return 0;
bool b=1;
int res=1;
for(auto e:g[n]){
if(p==e)continue;
auto t=dfs(e,n,sz,root);
res+=t;
if(t>sz/2)b=0;
}
if(!b||sz-res>sz/2)return res;
if(root!=-1)ch[root].push_back(n);
else s=n;
v.push_back(n);
used[n]=1;
for(auto e:g[n]){
dfs(e,n,dfs(e,n,g.size()*2,n),n);
}
return g.size()*2;
}
public:
centroid_decomposition(const graph&g):g(g){
int n=g.size();
used.resize(n);
ch.resize(n);
dfs(0,-1,n,-1);
}
int get_root(){return s;}
vector<int> operator[](int i){return ch[i];}
vector<int> get_euler_tour(){return v;}
};
#line 1 "give_us_tmp/centroid_decomposition.cpp"
/**
* @brief 重心分解
* 構築:O(NlogN)
* get_root() :出来上がった木の根を返す O(1)
* operator[](int i) :出来上がった木の子を返す
* get_euler_tour(int i):出来上がった木のdfs順を返す
*
* ・全てのパスについて調べる方法
* dfs順を取得してループを回し、
* パス上にあり、dfs順で最小となる頂点がiであるようなパスをなめていく
*
* verified with :https://judge.yosupo.jp/problem/frequency_table_of_tree_distance
* submission :https://judge.yosupo.jp/submission/28303
*/
class centroid_decomposition{
using graph=vector<vector<int>>;
graph g;
vector<int>used;
vector<int>v;
graph ch;
int s;
int dfs(int n,int p,int sz,int root){
if(used[n])return 0;
bool b=1;
int res=1;
for(auto e:g[n]){
if(p==e)continue;
auto t=dfs(e,n,sz,root);
res+=t;
if(t>sz/2)b=0;
}
if(!b||sz-res>sz/2)return res;
if(root!=-1)ch[root].push_back(n);
else s=n;
v.push_back(n);
used[n]=1;
for(auto e:g[n]){
dfs(e,n,dfs(e,n,g.size()*2,n),n);
}
return g.size()*2;
}
public:
centroid_decomposition(const graph&g):g(g){
int n=g.size();
used.resize(n);
ch.resize(n);
dfs(0,-1,n,-1);
}
int get_root(){return s;}
vector<int> operator[](int i){return ch[i];}
vector<int> get_euler_tour(){return v;}
};
Back to top page