競技プログラミング練習会2015 Normal 第4回

68
競技プログラミング練習会 2015 Normal 42015/05/08 長嶺英朗(ID:hnagamin)

Transcript of 競技プログラミング練習会2015 Normal 第4回

Page 1: 競技プログラミング練習会2015 Normal 第4回

競技プログラミング練習会2015 Normal

第4回

2015/05/08長嶺英朗(ID:hnagamin)

Page 2: 競技プログラミング練習会2015 Normal 第4回

●プライオリティキュー●Union-Find 木●ダイクストラ法●最小全域木問題

●プリム法●クラスカル法

目次

Page 3: 競技プログラミング練習会2015 Normal 第4回

プライオリティキュー

Page 4: 競技プログラミング練習会2015 Normal 第4回

● キューは以下のことができるデータ構造でした

思い出してください

●pushデータを入れる

●pop最後に入れたデータを取り出す

push

pop

Page 5: 競技プログラミング練習会2015 Normal 第4回

● プライオリティキューでは以下のことができます● “Priority” = 優先度

プライオリティキュー

●pushデータを入れる

●pop今までに入れたデータのうち、最も優先度の高いものを1つ取り出す

10

1

8push pop

8

2

42

23

42

Page 6: 競技プログラミング練習会2015 Normal 第4回

プライオリティキュー

● 先の2操作のほかに追加の操作をサポートするものもあります– 最も小さい要素の参照(peek)

– ある要素の優先度を下げる(decrease)

– 2つのプライオリティキューを併合する(meld)

Page 7: 競技プログラミング練習会2015 Normal 第4回

実装

● いろいろあります– 赤黒木(平衡二分探索木) push: O(log n) pop: O(log n)

– 二分ヒープ push: O(log n) pop: O(log n)

– フィボナッチヒープ push: O(1) pop: O(log n)

– Leftist Heap push: O(log n) pop: O(log n)● 各データ構造に長所・短所があるので目的に応じ

て使い分けてください– (時間の都合上、長所・短所については説明しません)

Page 8: 競技プログラミング練習会2015 Normal 第4回

C++におけるプライオリティキュー

● 朗報です● C++の標準ライブラリはプライオリティキューをサ

ポートしています

#include<queue>using namespace std;

priority_queue<int> q;// 入れた要素が大きい順に出てくる 

Page 9: 競技プログラミング練習会2015 Normal 第4回

C++におけるプライオリティキュー

● 朗報です● C++の標準ライブラリはプライオリティキューをサ

ポートしています

#include<queue>#include<vector>using namespace std;

priority_queue<int, vector<int>, greater<int> > q;// 入れた要素が小さい順に出てくる 

Page 10: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法

Page 11: 競技プログラミング練習会2015 Normal 第4回

復習: 最短経路問題

●頂点間の距離を求める問題●全点対最短経路問題…全ての頂点間の距離

●単一始点最短経路問題…ある点から各点への距離

1

0

23

1020

60

15

30頂点1 0: 20⇒頂点1 1: 0⇒頂点1 2: 35⇒頂点1 3: 65⇒

単一始点最短経路問題の例

Page 12: 競技プログラミング練習会2015 Normal 第4回

復習: ベルマンフォード法

●単一始点最短経路問題を解くアルゴリズム

●各頂点への暫定的な最短経路を保存しておいて、各辺を使うことで最短経路を更新できるか調べる

●計算量 O(VE)1

0

23

1020

60

15

30

頂点i 0 1 2 3

距離di 20 0 35 65

辺のリスト(0,1,10), (0,2,15), (1,0, 20), (1,2,60), (2,3,30)

d3 = 90 > d

2 + 30 = 65

(更新する)

Page 13: 競技プログラミング練習会2015 Normal 第4回

http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A

Page 14: 競技プログラミング練習会2015 Normal 第4回

GRL_1: Single Source Shortest Path

● 単一始点最短経路問題● 0 (≦ 各辺のコスト) 10≦ 4 ● V 10≦ 5

● E 5 × 10≦ 5

● ベルマンフォード法では解けない– VE > 1010

Page 15: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法

● 単一始点最短経路問題を解く● 負のコストの辺が存在しないとき使える● 計算量O(E log V)

– 辺の探索方法によって変わる

Page 16: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● 負の辺が無いことを仮定しています

Page 17: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● 最短距離が確定した頂点の集合Sと確定していない頂点の集合Tを考える

1

0

23

1050

10

15

30

S

T

コスト0

コスト10

Page 18: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● Sの頂点からTの頂点へ伸びる辺の集合E'をとる

1

0

23

1050

10

15

30

S

T

コスト0

コスト10

Page 19: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● Sの頂点の最短距離は確定しているので、E'の各終点(つまりTの幾つかの頂点)に対して暫定的な最短距離が計算できる

1

0

23

1050

10

15

30

S

T

コスト0

コスト10コスト≦10+30

コスト≦0+50

Page 20: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● ここで計算された暫定的な最短距離のうち最小のものをとると、これは実際最短距離である

1

0

23

1050

10

15

30

S

T

コスト0

コスト10コスト≦10+30

コスト≦0+50

Page 21: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● ここで計算された暫定的な最短距離のうち最小のものをとると、これは実際最短距離である

3

S

T

仮にこのようなより短い経路が存在したと仮定すると、

コスト≦10+30

Page 22: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● ここで計算された暫定的な最短距離のうち最小のものをとると、これは実際最短距離である

3

S

T

この経路のコストは非負なので、

コスト≦10+30

Page 23: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● ここで計算された暫定的な最短距離のうち最小のものをとると、これは実際最短距離である

3

S

T

この頂点の最短距離は40より小さくないといけない。これは最小のものをとったと言う仮定に矛盾する。

よってそのような経路は存在しない。コスト≦10+30

Page 24: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● ここで計算された暫定的な最短距離のうち最小のものをとると、これは実際最短距離である

1

0

23

1050

10

15

30

S

T

コスト0

コスト10コスト≦10+30

コスト≦0+50

Page 25: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法のアイデア

● 以上から新たな頂点の最短距離が確定し、Sが拡大する。このようにして1個ずつ最短距離を確定させていく

1

0

23

1050

10

15

30

S

T

コスト0

コスト10

Page 26: 競技プログラミング練習会2015 Normal 第4回

ダイクストラ法

● 暫定的最短距離が最小の頂点を探すときに「頂点を格納するプライオリティキュー」を使うと計算量を落とすことができる

● push回数はO(E)● キューの要素数はO(V)→挿入コストはO(log V)● 全体の計算量はO(E log V)● 実装については蟻本を読め(完)

Page 27: 競技プログラミング練習会2015 Normal 第4回

最小全域木問題

Page 28: 競技プログラミング練習会2015 Normal 第4回

● 以下、無向グラフのみを考えます● 連結かつ閉路のないグラフを木といいます

– 連結…どの2頂点間にも道がある– 閉路…始点と頂点が同じ道

木じゃない木じゃない

Page 29: 競技プログラミング練習会2015 Normal 第4回

最小全域木問題

● 辺に重みがある連結グラフが与えられる● この中の辺のいくつかを使って、与えられたグラフ

を木にしたい● 使用する辺の重みの合計を最小化せよ

Page 30: 競技プログラミング練習会2015 Normal 第4回

問題例

● いくつかの街が存在する● 街の間に道路を作ってどの街からどの街へも行け

るようにしたい● 道路を作るための費用が予めわかっている● 必要な道路作成費用を最小化せよ

街 ⇔ 頂点道路 ⇔ 辺費用 ⇔ 辺の重み(コスト)

Page 31: 競技プログラミング練習会2015 Normal 第4回

最小全域木問題を解くアルゴリズム

● 今日は2種類のアルゴリズムを紹介します– プリム法– クラスカル法

Page 32: 競技プログラミング練習会2015 Normal 第4回

プリム法

Page 33: 競技プログラミング練習会2015 Normal 第4回

プリム法

● 最小全域木問題を解く● 部分木を広げていくことで最小全域木を得る● 計算量O(E log E)

– E: 辺の本数, V: 頂点の数

– 辺の探索方法によって変わる

Page 34: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● 用語を定義します● グラフのある部分グラフSが木になっていて、かつS

を部分木として含む最小全域木が存在するとき、Sは「素敵な部分木である」ということにします

S

Page 35: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● いま、素敵な部分木Sがあるとします

● このときSを使ってより大きい素敵な部分木S'を作ることができます

● 作り方を示します

S

Page 36: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● Sの頂点以外の頂点の集合をTとする

S

T

Page 37: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● Sの頂点とTの頂点を結ぶ辺の集合E'をとる

S

T細い辺がE'の要素

Page 38: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● E'の要素のうちコストが最小の辺eをとる

S

T

e

Page 39: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● このとき、下のような部分木S'を考えると、S'は素敵な部分木である

S'

Page 40: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● このとき、下のような部分木S'を考えると、S'は素敵な部分木である

S e

仮定よりSを含む最小全域木が存在しますいま、eを含まない最小全域木が何かひとつ存在したとします

T

Page 41: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● このとき、下のような部分木S'を考えると、S'は素敵な部分木である

S e

このとき、この部分木にはSとTをつなぐ辺が必ず存在しますこれをe'とします

T

Page 42: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● このとき、下のような部分木S'を考えると、S'は素敵な部分木である

S e

ここにeを加えてみますすると、閉路が1つできます

T

e'

Page 43: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● このとき、下のような部分木S'を考えると、S'は素敵な部分木である

S e

e'を消去するとこれはまた木になります

T

Page 44: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● このとき、下のような部分木S'を考えると、S'は素敵な部分木である

S e

すると、e'のコストは絶対にeのコスト以上なので、これはまた最小全域木になります従って、S'を部分木に持つ最小全域木が少なくともひとつあることになります

T

Page 45: 競技プログラミング練習会2015 Normal 第4回

プリム法のアイデア

● こうして素敵な部分木Sを使ってより大きい素敵な部分木S'を作ることができました

● これを繰り返すことでグラフの頂点全体を使った素敵な部分木ができます。これが最小全域木です。

S'

Page 46: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

1.頂点を1個適当に取って、頂点が1つの素敵な部分木Sを作る (これは明らかに素敵な部分木ですよね)

2.SからTに伸びる辺のうちコストが最小の辺を1つ選び、その辺およびその辺に繋がっている頂点をSに追加する

3.全ての頂点を覆うまで2を繰り返す

Page 47: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

● 頂点としてCを選びます– どれを選んでも良い

● S = {C}

T = {A,B,D,E,F}

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 48: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

● SからTに伸びる辺の最小コストは2です

● よってこの辺と頂点Aを追加します

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 49: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

● SからTに伸びる辺の最小コストは1です

● よってこの辺と頂点Eを追加します

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 50: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

● SからTに伸びる辺の最小コストは5です

● よってこの辺と頂点Bを追加します

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 51: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

● SからTに伸びる辺の最小コストは3です

● よってこの辺と頂点Fを追加します

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 52: 競技プログラミング練習会2015 Normal 第4回

プリム法の動作

● SからTに伸びる辺の最小コストは3です

● よってこの辺と頂点Dを追加します

● これで最小全域木が完成しました

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 53: 競技プログラミング練習会2015 Normal 第4回

プリム法の計算量

● コストの小ささを優先度として辺を格納するプライオリティキューを利用するとO(E log E)となる

● 実装については蟻本を読め

Page 54: 競技プログラミング練習会2015 Normal 第4回

クラスカル法

Page 55: 競技プログラミング練習会2015 Normal 第4回

クラスカル法

● 最小全域木問題を解く● 辺をコストが小さい順に見ていき、閉路ができない限り追加していく

● O(E log E)

Page 56: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● 辺のコストが小さい順に見ていきます

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 57: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● コスト1の辺が最小です

● AとEは繋がっていないので、この辺を使います

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 58: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● コスト2の辺が最小です

● AとCは繋がっていないので、この辺を使います

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 59: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● コスト3の辺が最小です

● FとBは繋がっていないので、この辺を使います

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 60: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● コスト4の辺が最小です

● CとEは既に繋がっているので、この辺は使いません

D

F

C

B

E

A1

2

3

4

56

7

8

9

Page 61: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● コスト5の辺が最小です

● BとEは繋がっていないので、この辺を使います

D

F

C

B

E

A1

2

3

56

7

8

9

Page 62: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● コスト6の辺が最小です

● CとDは繋がっていないので、この辺を使います

D

F

C

B

E

A1

2

3

56

7

8

9

Page 63: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● 7,8,9の辺は全て使いません● これで最小全域木が完成します

D

F

C

B

E

A1

2

3

56

Page 64: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の動作

● このようなアルゴリズムで最小全域木が求まることは、プリム法と同様の形式で示すことができます

D

F

C

B

E

A1

2

3

56

7

8

9

e

Page 65: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の計算量

● Union-Find 木というデータ構造を使うと、繋がってるか否かの判断を効率的に行うことができる– 「繋がっている」「繋がっていない」を「同じ集合に属す」

「属さない」とみる

Page 66: 競技プログラミング練習会2015 Normal 第4回

// ここでUnion-Find 木の話をする

Page 67: 競技プログラミング練習会2015 Normal 第4回

クラスカル法の計算量

● 辺のソートにO(E log E)かかる● 各辺について頂点が繋がっているか判定するのに

O(α(E))かかる

– 全体でO(E・α(E))

– α(n)は逆アッカーマン関数

● よって全体の計算量は

O(E log E + E α(E)) = O(E log E)

Page 68: 競技プログラミング練習会2015 Normal 第4回

α (222 65536

−3)=4