const int maxn = 100000 + 5; //树中节点个数
//边集
struct Edge{
int v,pre,c;
}Es[maxn * 2];
int head[maxn],TOT_EDGE;
void INIT_EDGE(){ //边集初始化
memset(head,-1,sizeof head);
TOT_EDGE = 0;
}
void ADD_EDGE(int u,int v,int c){ //添加边
Es[TOT_EDGE].v = v;
Es[TOT_EDGE].c = c;
Es[TOT_EDGE].pre = head[u];
head[u] = TOT_EDGE++;
}
/**树链剖分部分*/
/**
** son: 节点重儿子
** fa: 节点父节点
** dep: 节点在树中深度
** size: 节点子树的大小
** top: 节点在重链中的深度最低节点(最高节点)
** tid: 节点编号(hash值)
** RANK: RANK[v]编号为v的是第RANK[v]节点
** SegSize:用于编号的迭代辅助变量,最小编号为SegSize的初始值
*/
int son[maxn],fa[maxn],dep[maxn],size[maxn];
int top[maxn],tid[maxn],RANK[maxn],SegSize;
int DFS(int rt){
dep[rt] = dep[fa[rt]] + 1;
son[rt] = 0;
size[rt] = 1;
for(int i = head[rt];~i;i = Es[i].pre){
int v = Es[i].v;
if(v != fa[rt]){
fa[v] = rt;
size[rt] += DFS(v);
if(size[son[rt]] < size[v]) son[rt] = v;
}
}
return size[rt];
}
void Split(int rt,int tp){
top[rt] = tp;
tid[rt] = ++SegSize;
RANK[tid[rt]] = rt;
if(son[rt]){
Split(son[rt],tp);
for(int i = head[rt];~i;i = Es[i].pre){
int v = Es[i].v;
if(v != fa[rt] && v != son[rt]) Split(v,v);
}
}
}
void TreeLineSplit(){ //开始剖分
dep[0] = 0;
size[0] = 0;
fa[1] = 0;
DFS(1);
SegSize = -1;
Split(1,1);
}
树链剖分模板
最新推荐文章于 2021-07-25 17:09:52 发布