inteval(int v, int last){ if (par[v] == -2 || pre[par[v]] < last) return v; int u = eval(par[v], last); par[v] = u; if (pre[label[u]] < pre[label[v]]) label[v] = label[u]; return v; }
boolsemiNca(int n, int r){ par.assign(n, -1); par[r] = -2; idom.resize(n); idom[r] = -1; pre.resize(n); post.resize(n); dfs(r); semi.resize(n); label.resize(n); idom.resize(n); REP(i, n) { label[i] = semi[i] = i; idom[i] = par[i]; if (par[i] == -1) returnfalse; } for (size_t i = seq.size() - 1; i; i--) { int v = seq[i]; for (arc &a: ee[v]) { int w = label[eval(a.v, i+1)]; if (pre[w] < pre[semi[v]]) semi[v] = w; } label[v] = semi[v]; } for (size_t i = 1; i < seq.size(); i++) { int v = seq[i]; while (pre[idom[v]] > pre[semi[v]]) idom[v] = idom[idom[v]]; } returntrue; }
intmain(){ int n, i, j, c; cin >> n; e.resize(n); ee.resize(n); while (cin >> i >> j) { e[i].push_back(arc{j, 0}); ee[j].push_back(arc{i, 0}); } if (!semiNca(n, 0)) return0; REP(i, n) printf("%d: %d\n", i, idom[i]); }
Testdata
The following tests helped me diagnose bugs in my semi-NCA implementation.
voididfs(int n, int r){ bool changed; pre.resize(n); post.resize(n); seq.clear(); idom.assign(n, -1); idom[r] = -2; dfn = 0; dfs(r); do { changed = false; for (int i = seq.size() - 2; i >= 0; i--) { int v = seq[i], x = -1; for (arc &a: ee[v]) { if (x == -1) x = a.v; else { int y = a.v; while (x != y) { if (pre[x] > pre[y]) x = idom[x]; else y = idom[y]; } } } if (x != idom[v]) { idom[v] = x; changed = true; } } } while (changed); }
intmain(){ int n, i, j, c; cin >> n; e.resize(n); ee.resize(n); while (cin >> i >> j) { e[i].push_back(arc{j}); ee[j].push_back(arc{i}); }
idfs(n, 0); REP(i, n) printf("%d: %d\n", i, idom[i]); }
Depth Based Search
After insertion of (x,y), v is affected iff depth(nca)+1 < depth(v) && exists path P from y to v s.t depth(v) <= depth(w) and d(v) is changed to nca