木のCentroid Decomposition
分割統治っぽくなって,頂点数Nの部分木にたいしてO(f(n))の計算量がかかるとすると,全体の計算量はCentroid DecompositionをするとO(f(n) log n)になってはやい.
追記:コードに誤りがあったので修正しました.まだあるかもしれない
#include <cstdio> #include <vector> #include <algorithm> using namespace std; typedef pair<int, int> P; #define to first #define length second const int INF = 1 << 29; const int MAXN = 10000; vector<P> G[MAXN]; bool centroid[MAXN]; int subtree_size[MAXN]; //部分木の大きさを計算 int compute_subtree_size(int v, int p){ int c = 1; for(int i=0;i<G[v].size();i++){ int w = G[v][i].to; if(w==p || centroid[w]) continue; c+=compute_subtree_size(w,v); } subtree[v] = c; return c; } //重心を求める pair<int,int> search_centroid(int v, int p, int t){ pair<int,int> res = make_pair(INF, -1); int s=1, m=0; for(int i=0;i<G[v].size();i++){ int w = G[v][i].to; if(w==p || centroid[w]) continue; res = min(res, search(w,v,t)); m=max(m,subtree[w]); s+=subtree[w]; } m=max(m, t-s); res = min(res, make_pair(m,v)); return res; } void solve_subproblem(int v){ compute_subtree_size(v, -1); int s = search_centroid(v,-1,subtree[v]); centroid[s] = true; for(int i=0;i<G[s].size();i++){ if(centroid[G[s][i].to])continue; solve_subproblem(G[s][i].to); } //ここに処理をかく centroid[s] = false; } void solve(){ solve_subproblem(0); }