More Related Content
Similar to 図と実装で理解する『木構造入門』 (8)
図と実装で理解する『木構造入門』
- 6. 木構造入門
1. 木構造とは
i. 木構造
ii. 根つき木
iii. 根つき木の実装
2. DFS木
I. 深さ優先探索とDFS木
II. DFS木の作り方
III. DFS木と部分木
3. Euler Tour
I. Euler TourとLCA
6
- 7. 木構造入門
1. 木構造とは
i. 木構造
ii. 根つき木
iii. 根つき木の実装
2. DFS木
I. 深さ優先探索とDFS木
II. DFS木の作り方
III. DFS木と部分木
3. Euler Tour
I. Euler TourとLCA
7
- 20. 木構造入門
1. 木構造とは
i. 木構造
ii. 根つき木
iii. 根つき木の実装
2. DFS木
I. 深さ優先探索とDFS木
II. DFS木の作り方
III. DFS木と部分木
3. Euler Tour
I. Euler TourとLCA
20
- 31. DFS木を作る実装
• 再帰関数でDFSをする
vector<int> children[N]; //もとの子
int par[N],pos[N]; //DFS木における親、DFS終了時のカウンターの状態
int c = 0; //cはカウンターでDFS木のノード番号になる
void dfs(int v){ //vはもとのノード番号
int dfsOrder = c;
c++;
for(int i=0; i<children[v].size(); i++){
par[c] = dfsOrder;
dfs(children[v][i]);
}
pos[dfsOrder] = c;
} //変数が「もと」か「あと(DFS木)」かどちらを表しているのか混乱しないように注意
31
- 37. 補足:RAQとRUQとRMQ
• RAQ:Range Add Query
配列の特定の区間に対して値を加算する
• RUQ:Range Update Query
配列の特定の区間に対して値を変更する
• どちらも遅延評価Segment Treeや平方分割で
実装できます
• RMQ:Range Minimum Query
配列の特定の区間の値の最小値を求める
も後で出てきます
37
- 38. 木構造入門
1. 木構造とは
i. 木構造
ii. 根つき木
iii. 根つき木の実装
2. DFS木
I. 深さ優先探索とDFS木
II. DFS木の作り方
III. DFS木と部分木
3. Euler Tour
I. Euler TourとLCA
38
- 41. 5
Euler Tour
• 頂点のDFSでの訪問順を
vector等で持つことで、木を
直線にできる
• 0,1,2,1,0,3,0,4,5,4,6,4,0
• この配列の要素数は頂点数を
Nとして2N-1個になる
41
2
1
0
3
4
6
- 42. Euler Tourの実装
vector<int> EulerTour;
int pre[N];
void dfs(int v){
pre[v] = EulerTour.size();
EulerTour.push_back(v);
for(int i=0; i<children[v].size(); i++){
dfs(edge[v][i]);
EulerTour.push_back(v);
}
}
• 関数名がdfsでさっきと被ってるが、その辺りは臨機応変に対
応する
42
- 43. 2
深さ
• ところで、あるノードの根から
の距離を深さと呼ぶ
• 再帰関数で求められる
int depth(int v){
if(par[v] == -1) return 0;
return depth(par[v])+1;
}
• 木の構造が変わらないならメモ
化するとよい
int d[N] = {};
int depth(int v){
if(par[v] == -1) return 0;
if(d[v] != 0) return d[v];
return d[v] = depth(par[v])+1;
}
43
2
1
0
1
1
2
- 47. 5
LCAとRMQ
• さっきのスライドより右の木
のEuler Tourは
0,1,2,1,0,3,0,4,5,4,6,4,0
• 頂点vを最初に訪問した時の
pushする前のvectorの要素
数をpre[v]とする
47
2
1
0
3
4
6
- 48. 5
LCAとRMQ
• さっきのスライドより右の木
のEuler Tourは
0,1,2,1,0,3,0,4,5,4,6,4,0
• 頂点vを最初に訪問した時の
pushする前のvectorの要素
数をpre[v]とする
• 2つの頂点i, j (pre[i] < pre[j])
のLCAは
RMQ[pre[i],pre[j])になる
48
2
1
0
3
4
6
pre[0] = 0
pre[1] = 1
pre[2] = 2
pre[3] = 5
pre[4] = 7
pre[5] = 8
pre[6] = 10
- 49. LCAとRMQ
•
0,1,2,1,0,3,0,4,5,4,6,4,0
49
pre[0] = 0
pre[1] = 1
pre[2] = 2
pre[3] = 5
pre[4] = 7
pre[5] = 8
pre[6] = 10
- 50. LCAとRMQ
50
pre[0] = 0
pre[1] = 1
pre[2] = 2
pre[3] = 5
pre[4] = 7
pre[5] = 8
pre[6] = 10
Euler Tour 0 1 2 3 4 5 6 7 8 9 10 11 12
v 0 1 2 1 0 3 0 4 5 4 6 4 0
- 51. LCAとRMQ
51
Euler Tour 0 1 2 3 4 5 6 7 8 9 10 11 12
v 0 1 2 1 0 3 0 4 5 4 6 4 0
v 0 1 2 3 4 5 6
pre[v] 0 1 2 5 7 8 10
- 57. 練習問題
• AOJ GRL_5_C LCA
https://onlinejudge.u-
aizu.ac.jp/courses/library/5/GRL/5/GRL_5_C
• AOJ GRL_5_D Range Query on a Tree
https://onlinejudge.u-
aizu.ac.jp/courses/library/5/GRL/5/GRL_5_D
• 最初はAOJで基礎を固めるのがおすすめです
57
- 58. 練習問題
• JOI春合宿2015 Day2-3 Road Development
https://atcoder.jp/contests/joisc2015/tasks/j
oisc2015_g
• このスライドの内容をすべて網羅しているよう
な問題で、難しく重実装ですが、これさえ解け
ればかなり力が付きます
58