teamnote history merge
This commit is contained in:
51
2025fall/source/Graph/DominatorTree.cpp
Normal file
51
2025fall/source/Graph/DominatorTree.cpp
Normal file
@@ -0,0 +1,51 @@
|
||||
// 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
|
||||
Reference in New Issue
Block a user