關於樹鏈剖分html
模板:數組
1 const int MAXN = 20010; 2 struct Edge 3 { 4 int to,next; 5 } edge[MAXN*2]; 6 int head[MAXN],tot; 7 8 int top[MAXN];//top[v]表示v所在的重鏈的頂端節點 9 int fa[MAXN]; //父親節點 10 int deep[MAXN];//深度 11 int num[MAXN];//num[v]表示以v爲根的子樹的節點數 12 int p[MAXN];//p[v]表示v與其父親節點的連邊在線段樹中的位置 13 int fp[MAXN];//和p數組相反 14 int son[MAXN];//重兒子 15 int pos; 16 17 int n; 18 19 void init() 20 { 21 tot = 0; 22 memset(head,-1,sizeof(head)); 23 pos = 1;//序號實際上是從1開始? 24 memset(son,-1,sizeof(son)); 25 } 26 void addedge(int u,int v) 27 { 28 edge[tot].to = v; 29 edge[tot].next = head[u]; 30 head[u] = tot++; 31 } 32 void dfs1(int u,int pre,int d) //第一遍dfs求出fa,deep,num,son 33 { 34 deep[u] = d; 35 fa[u] = pre; 36 num[u] = 1; 37 for(int i = head[u]; i != -1; i = edge[i].next) 38 { 39 int v = edge[i].to; 40 //由於路徑是雙向的,因此不能等於父及誒單 41 if(v != pre) 42 { 43 //先遞歸地找到兒子節點的深度,父節點,子節點數目等信息 44 dfs1(v,u,d+1); 45 //更新u節點的兒子數目 46 num[u] += num[v]; 47 if(son[u] == -1 || num[v] > num[son[u]])//求出重兒子 48 son[u] = v; 49 } 50 } 51 } 52 53 //由於對於輕兒子來講,top[u]=u,對於重兒子來講,若是son[v]!=-1,那麼top[v]=top[son[v]] 54 void getpos(int u,int sp) //第二遍dfs求出top和p 55 { 56 top[u] = sp; 57 //先找重兒子 58 if(son[u] != -1) 59 { 60 //把邊的位置標記一下 61 p[u] = pos++; 62 //fp至關因而p的反函數? 63 fp[p[u]] = u; 64 //更新重兒子 65 getpos(son[u],sp); 66 } 67 //若是到了葉子節點 68 else 69 { 70 //再也不向下dfs 71 p[u] = pos++; 72 fp[p[u]] = u; 73 return; 74 } 75 //更新其餘的節點 76 for(int i = head[u] ; i != -1; i = edge[i].next) 77 { 78 int v = edge[i].to; 79 if(v != son[u] && v != fa[u]) 80 getpos(v,v); 81 } 82 }