参考博客0
参考博客1
半支配点
支配树的生成方法实在难懂,网上博客多少有点表述不清。暂时先只掌握支配树的性质,存下求树的模板,日后再补上求树过程。
HDU 4694
模板题,ksf代码初始化有点问题,AC代码:
#include <cstdio>
#include <algorithm>
#include <iostream>
typedef long long ll ;
using namespace std;
//DT.init(n) -> DT.add(u,v) -> DT.work(root);
//DT.idom[i] : i 的最近支配点(root 到 i 距离 i 最近的必经点)
//需要完整的支配树用 idom[i]作为 fa[i]建树即可
const int N = 50005, M = 100005; //N 点数,M 主函数中调用 add 的次数
struct Dominator_Tree{
private: struct eg{
int v, next; }e[M*2+N];
int tot, cnt, h[N], iw[N], li[N], fa[N], fo[N], vo[N], sdom[N], pre[N], bkt[N];
inline void link(int h[],int u,int v){
e[++cnt] = {
v,h[u]}, h[u] = cnt; }
inline int eval(int p){
findf(p); return vo[p]; }
int findf(int p){
if(fo[p] == p) return p;
int r = findf(fo[p]);
if(sdom[vo[fo[p]]] < sdom[vo[p]]) vo[p] = vo[fo[p]];
return fo[p] = r;
}
void dfs(int p){
sdom[p] = iw[p] = ++tot, li[tot] = p;
for(int i = h[p]; i; i = e[i].next)
if(!iw[e[i].v]) dfs(e[i].v), fa[e[i].v] = p;
}
public: int idom[N];
inline void add(int u, int v) {
link(h, u, v), link(pre, v, u);}
inline void work(int root){
dfs(root); int p, fp;
for(int j = tot; j >= 2; j--, bkt[fp] = 0){
for(int i = pre[p=li[j]]; i; i=e[i].next)
if(iw[e[i].v]) sdom[p] = min(sdom[p], sdom[eval(e[i].v)]);
link(bkt, li[sdom[p]], p);
for(int i = bkt[fp=fo[p