樹鏈剖分 模板

關於樹鏈剖分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 }
相關文章
相關標籤/搜索