52 lines
1.5 KiB
C++
52 lines
1.5 KiB
C++
// https://ideone.com/aO6cH4
|
|
namespace dtree{ // by cki86201
|
|
vector<int> E[N], RE[N], rdom[N];
|
|
int S[N], RS[N], cs;
|
|
int par[N], val[N], sdom[N], rp[N], dom[N];
|
|
void clear(int n) { cs = 0;
|
|
for(int i=0;i<=n;i++) {
|
|
par[i] = val[i] = sdom[i] = rp[i] = dom[i] = S[i] = RS[i] = 0;
|
|
E[i].clear(); RE[i].clear(); rdom[i].clear();
|
|
}
|
|
}
|
|
void add_edge(int x, int y) { E[x].push_back(y); }
|
|
void Union(int x, int y) { par[x] = y; }
|
|
int Find(int x, int c = 0) {
|
|
if(par[x] == x) return c ? -1 : x;
|
|
int p = Find(par[x], 1);
|
|
if(p == -1) return c ? par[x] : val[x];
|
|
if(sdom[val[x]] > sdom[val[par[x]]]) val[x] = val[par[x]];
|
|
par[x] = p;
|
|
return c ? p : val[x];
|
|
}
|
|
void dfs(int x) {
|
|
RS[ S[x] = ++cs ] = x;
|
|
par[cs] = sdom[cs] = val[cs] = cs;
|
|
for(int e : E[x]) {
|
|
if(S[e] == 0) dfs(e), rp[S[e]] = S[x];
|
|
RE[S[e]].push_back(S[x]);
|
|
}
|
|
}
|
|
int solve(int s, int *up) { // Calculate idoms
|
|
dfs(s);
|
|
for(int i=cs;i;i--) {
|
|
for(int e : RE[i]) sdom[i] = min(sdom[i], sdom[Find(e)]);
|
|
if(i > 1) rdom[sdom[i]].push_back(i);
|
|
for(int e : rdom[i]) {
|
|
int p = Find(e);
|
|
if(sdom[p] == i) dom[e] = i;
|
|
else dom[e] = p;
|
|
}
|
|
if(i > 1) Union(i, rp[i]);
|
|
}
|
|
for(int i=2;i<=cs;i++) if(sdom[i] != dom[i]) dom[i] = dom[dom[i]];
|
|
for(int i=2;i<=cs;i++) up[RS[i]] = RS[dom[i]];
|
|
return cs;
|
|
}
|
|
} // namespace dtree
|
|
|
|
int par[N];
|
|
dtree::add_edge(a, b); // a -> b
|
|
int cnt = dtree::solve(s, par);
|
|
// cnt : s에서 도달할 수 있는 정점, par: dominator tree의 par
|