プログラミング言語i 第10回 最短経路問題 · プログラミング言語i 第10回...

43
プログラミング言語I 10最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤 和人

Upload: doandang

Post on 17-Aug-2018

252 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

プログラミング言語I 第10回

短経路問題

埼玉大学工学部電気電子システム工学科

伊藤 和人

Page 2: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路問題とは

始点から終点へ行く経路が複数通りある場合に、 も短い経路を見つける問題

経路の短さの決め方によって様々な応用

Page 3: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路問題の応用例

カーナビゲーション

現在地から目的地まで 短時間のルート

経路=道路

交差点において走る道路を変更してもよい

経路の短さ=所要時間の短さ

鉄道乗り換え案内

始発駅から目的駅まで料金 低のルート

経路=路線

駅において路線を乗り換えてもよい

経路の短さ=料金の安さ

Page 4: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

問題の定式化

定式化: 問題の意味が変化しないことに注意して、明確な形式に問題を整理すること

条件と解の性質を明確にする

あいまいな点をなくす

さらに、問題を解くプログラムが容易に作成できるような定式化を行うことが重要

Page 5: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

グラフ

プログラミングに適した問題定式化の道具としてよく用いられる

1個以上の点(ノード)と2つの点を結ぶ枝からなる

点 枝

グラフの例

Page 6: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

グラフ(その2)点を共有する枝の集合をパス(path、経路)という

パスの始点と終点を定める

一般に始点と終点が同じパスは複数通り存在する(1通りしか存在しない場合や、1つも存在しない場合あり)

始点終点

パス

Page 7: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

グラフ(その3)

枝に重みを与える

パスの重みは、枝重みの和とする

始点終点

パス: 重み12

2

1

9

63

5

2

2

始点・終点が同じ複数通りのパス

パスによって重みは異なる

枝重み

Page 8: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路問題の定式化

グラフによって問題を入力            (始点、終点、枝重み)

鉄道乗り換え案内の場合

乗換駅を点、枝重みを料金とすればよい

横浜

品川東京 上野

赤羽 大宮

池袋新宿渋谷

重み 小のパスを見つける

280円

260円

160円150円 150円 150円

290円160円

160円150円160円

2,750円

Page 9: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

小値原理

始点sから終点tへの 短経路上の点をvとすると、パスp(s,v)とパスp(v,t)はともに

短経路である

s始点 終点

sからtへの 短経路

tsからvへの短経路

vからtへの短経路

v

終点以外の 短経路を順次求めて、終的に終点への 短経路を求める

Page 10: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

問題の分類

枝重みが0または正の場合

枝重みが0、正、負で負ループがない場合

枝重みが0、正、負で負ループがある場合

ループ: 始点と終点が一致したパス

負ループ: 枝重み和が負のループ

負ループ: 重み-2

2

1

-8

13

5

2

0枝重みが0、正、負で負ループがある場合

Page 11: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路アルゴリズム1

枝重みが0または正の場合を考える

始点sから点bへの短経路が1である

と決定できる

なぜか?

21

s36

a

d

b

c

0

3 2

41 0

2

始点

始点sから他の点への 短経路を求める

21

s36

a

d

b

c

0

3 2

41 0

2

始点

Page 12: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路アルゴリズム1(その2)

枝重みが0または正の場合

21

s36

a

d

b

c

0

3 2

41 0

2

枝重みが0または正であるので、点a, c, dを経由するどのパスも重みが1以上となるため

始点

2

3

6

cを経由パス重みは3以上

dを経由パス重みは6以上

aを経由パス重みは2以上1

Page 13: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

1

短経路アルゴリズム1(その3)次に経路が 短な点を求める

始点

21

s36

a

d

b

cf

e0

3 2

41 0

2

2 4

53

6

121

s36

a

d

b

cf

e

3 2

41 0

2

02 4→2

53

6

1

22

1

s36

a

d

b

cf

e

3 2

41 0

2

0 2

53

6

1

2 22

1

s36

a

d

b

cf

e

3 2

41 0

2

0

5→43

6

Page 14: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路アルゴリズム1(その4)

アルゴリズムのポイント

短経路長の定まった点から、さらに枝1本で到達する点のうち、経路長 短の点は、 短経路と決定できる

1

2

s

7

3

42

2

4

53

4

6

6

7

短経路長の決まっている点

さらに枝1本で到達する点

経路長が 小⇒ 短経路を決定できる点

ダイクストラ法

Page 15: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

C言語によるグラフ表現1

2次元配列を用いる方法

枝が結ぶ2点(i,j)

配列要素e[i][j]が枝を表す

i⇒j と j⇒i を区別しない場合e[j][i] = e[i][j] とする

ji

e[i][j]=1: 枝あり

e[i][j]=0: 枝なし

Page 16: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

C言語によるグラフ表現1(続き)

枝(i,j)の重み ・・ w[i][j]が記憶

i⇒j と j⇒i を区別しない場合w[j][i] = w[i][j] とする

ji

w[i][j]

Page 17: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

ダイクストラ法の実装

int s, minLen, j, m, u[N], f[N]={0};for( j=0 ; j<N ; j++ ) u[j] = 9999;s = 0; u[s] = 0; for( m=1 ; m<N ; m++ ){

f[s] = 1;for( j=0 ; j<N ; j++ ){

if( e[s][j] != 1 ) continue;if( u[s]+w[s][j] < u[j] ) u[j]=u[s]+w[s][j];

}minLen = 9999;for( j=0 ; j<N ; j++ ){

if( f[j] == 1 ) continue;if( u[j] < minLen ){ minLen = u[j]; s = j; }

}}

十分大きな正数

枝(s,j)が存在しない

始点

s=0と

する

短経路既定の点は除外

点sは 短経路決定

点数N

点sは経路長が 短

点jへの経路長を更新

Page 18: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

長さだけでなく経路を記録

int s, minLen, j, m, u[N], f[N]={0}, prev[N];for( j=0 ; j<N ; j++ ) u[j] = 9999;s = 0; u[s] = 0; for( m=1 ; m<N ; m++ ){

f[s] = 1;for( j=0 ; j<N ; j++ ){

if( e[s][j] != 1 ) continue;if( u[s]+w[s][j] < u[j] ){

u[j]=u[s]+w[s][j]; prev[j]=s; } /* jの直前はs */}minLen = 9999;for( j=0 ; j<N ; j++ ){

if( f[j] == 1 ) continue;if( u[j] < minLen ){ minLen = u[j]; s = j; }

}}

十分大きな正数

枝(s,j)が存在しない

始点

s=0と

する 点sは 短経路決定

点数N

点sは経路長が 短

点jへの経路長を更新

短経路既定の点は除外

Page 19: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

ダイクストラ法の計算複雑度

経路長 短の点を1つ選び経路を決定

その点から1本の枝で接続する点について経路長を調べなおす

すべての点について経路が決定するまで繰り返す

)( 2NO

Page 20: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

プログラムの実行時間

ノード数Nとプログラム実行時間の関係

0.01

0.10

1.00

10.00

100.00

100 1000 10000 100000N

PentiumIV2.4GHz512MBメモリ

予想

N=8000約500Mバイト

N=7000約400Mバイト

1つのノード当たり4本の枝の場合

Page 21: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

プログラムの問題点

配列による枝表現はメモリを大量に必要とし、かつ効率が悪い

010000000000000000000000000000000000000000000000000000101000000000000000000011000000000000000000000000000000010110000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000000000000000001101000000000000000000000000000000000000000000000000000010110000000000000000000000000000000000000000000000000001010000000000000000000000000000000000000001000000000001100000000000000000000000000000000000000100000100000000000110000000000000000000000000000000000000000100000000001010000000000000000000000000000000000000000000000000001101000000000000000000000000000000000000000010000000000010100000000000000000000000000000000000100000000000000001010000000000000000000000000000000000000000000000000000101001000000000000000000000000000000000010000000000000010100100000000000000000000000000000000000000000000000001000000000000000000000000000000010100000000000000000000001000000100000000000000000000101000000000000000000010010100000000000000000000000000000000000000000000000001001010000000010000000000000000000000000000000000000000000101000000000000000000000000000000000000000000000000000010100000000000000000000000000010000000000000000000000001000000000001001000000000000000000010000000000000000000001000000000000000000000000001000010000000000000000000010100000000000000000000000000000…

j

i

枝の有無を表す2次元配列e[i][j]の例

0がほとんど

Page 22: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

配列による枝表現の問題

枝の有無(e[i][j]==1か否か)を調べる処理が必要

枝が無くても(e[i][j]=0)を記憶する必要があるためメモリを大量に消費し、速度低下(スラッシング)

配列に代わる、不規則なデータを効率よく記録する方式が必要

リスト構造

Page 23: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

リストの管理

リストの要素データ領域の他に、次の要素を指すポインタを備える

ポインタを用いて要素をつなげる=リスト

データ領域

ポインタ

要素

次の要素を指す

Page 24: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

リストの実装

構造体によって、データ領域と次要素へのポインタをまとめて管理する

要素の構造体型を宣言

typedef struct Edge {struct Edge *next; int i,j; // 点1, 点2int w; // 枝重み

} EDGE;

次要素へのポインタ

データ領域

リストの先頭を指すポインタを宣言

EDGE *edge_top = NULL;

Page 25: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

リストの実装(その2)

リストの例

リストを順にたどる処理

edge_topNULL

点2枝重み

点2枝重み

点2枝重み

点1 点1 点1

3本の枝を記録するリスト

リストの末尾ではnextメンバはNULL

EDGE *ep;for( ep=edge_top ; ep != NULL ; ep=ep->next ){… /* リスト要素に対する処理 */

}

Page 26: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

ダイクストラ法における枝リスト

短経路が決まるたびに、その点から枝1本でつながる点の経路長更新

1

2

s

7

3

42

2

4

53

4

6

6

短経路長の決まっている点

経路長を更新する点

新たに 短経路長の決まった点

各点に接続する枝リストがあると便利

7

Page 27: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

ダイクストラ法のための枝リスト

各点に接続する枝のリストNULL

点2枝重み

点2枝重み

点2枝重み

0 0 0edge[0]

NULL

点2枝重み

点2枝重み

点2枝重み

1 1 1edge[1]

edge[2]

点2枝重み

1

点ごとに接続する枝数は変化

点2枝重み

2

点0に接続する枝のリスト

点1に接続する枝のリスト

ダイクストラ法と組合わせる場合、メンバ「点1」は不要

Page 28: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

リストを用いたダイクストラ法

int s, minLen, j, m, u[N], f[N]={0};EDGE edge[N], *ep; /* 枝リストを設定する処理は省略 */for( j=0 ; j<N ; j++ ) u[j] = 9999;s = 0; u[s] = 0; for( m=1 ; m<N ; m++ ){

f[s] = 1;for( ep=edge[s] ; ep!=NULL ; ep=ep->next ){

if( u[s]+ep->w < u[ep->j] ){u[ep->j]=u[s]+ ep->w;}

}minLen = 9999;for( j=0 ; j<N ; j++ ){

if( f[j] ) continue;if( u[j] < minLen ){ minLen = u[j]; s = j; }

}}

十分大きな正数

始点

s=0と

する

短経路既定の点は除外

点sは 短経路決定

点数N

点sは経路長が 短

sに接続する枝を順に調べる

点ep->jへの経路長を更新

Page 29: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

プログラムの実行時間

ノード数Nとプログラム実行時間の関係

0.01

0.10

1.00

10.00

100.00

100 1000 10000 100000N

PentiumIV2.4GHz512MBメモリ

リスト構造利用

配列利用N=8000約500Mバイト

N=7000約400Mバイト

N=40000約1Mバイト

Page 30: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

短経路アルゴリズム2

負の枝重みが存在する場合

21

s36

a

d

b

c

0

3 -1

-41 0

-2

始点

ダイクストラ法では 短経路を見つけられない

なぜか?

まだ 短経路の決まっていない点を経由した方が経路長が短くなるパスが存在するかもしれないため

Page 31: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

Bellman方程式

点jの 短経路長をujとするとき、

ujが満たす関係式・・・Bellman方程式

{ } sjwuu ijii

j ≠∀+= min

0=su

wiji j始点 s

uiuj

小値原理より

Page 32: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

Bellman方程式を解く

Bellman方程式の解= 短経路

漸化的に解く

u[i]が更新されたら、枝(i,j)が存在する点jについてu[j]を更新する

すべての点jについてu[j]が変化しなくなったら、解が得られている

Bellman-Ford法

Page 33: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

リストを用いたBellman-Ford法実装

int s,update,minL,i,u[N], prev[N];EDGE *edge_top, *ep;

for( i=0 ; i<N ; i++ ) u[i] = 9999;s = 0; u[s] = 0;do {

update = 0;for( ep=edge_top ; ep != NULL ; ep=ep->next ){

if( u[ep->i]+ep->w < u[ep->j] ){u[ep->j] = u[ep->i]+ ep->w;prev[ep->j] = ep->i;update = 1;

}}

} while ( update );

十分大きな正数

/*リストを正しく作成する必要あり(ここでは省略) */

始点

s=0と

する

経路を記録

経路長が短くなったら更新フラグを1に

経路長更新の場合再度繰り返し

Page 34: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

do - while文

条件が成り立つ間、文を実行

do 文 while( 式 );

意味: まず1回文を実行する。    式が真の間、文を実行。

True

False

True

False

do-while文の実行の様子 “while(式) 文;”の実行の様子

Page 35: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

Bellman-Ford法の計算複雑度

すべての枝を順に調査

経路長が更新されたら、再度調査実行

負ループがなければ 短経路を構成する枝数はN未満・・・更新は高々N-1回

)(NEO実行時間

Page 36: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

負ループのある 短経路問題

短経路は不定⇒ 負ループを繰り返すごとに経路長は減少

「経路にループを含まない」という制約を与えると意味のある問題として定式化される

効率よく 短経路を求めるアルゴリズムは見つかっていない

負ループが存在する場合の 短経路問題は負ループが存在しない場合の問題とは性格が異なる

Page 37: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

組み合わせ 適化問題

ある条件を満足する解候補のうち、ある評価尺度が 適になる解を選ぶ問題

例: 短経路問題

条件: 始点から終点への連続した枝集合(経路)

評価尺度: 枝重み和が小さい

Page 38: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

組み合わせ 適化問題の困難さ

組み合わせ 適化問題を3つに分類

P: 多項式可解な問題

問題サイズの多項式オーダの手数で解が得られる⇒計算複雑度が多項式オーダの解法が存在

NP: 非決定的多項式可解な問題

都合良く選択肢を選ぶと、問題サイズの多項式オーダの手数で解が得られる

PでもNPでもない問題

PやNPよりも難しい問題

Page 39: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

問題の困難さ

組み合わせ 適化問題の分類とその関係

P問題の例ソート(並べ替え)短経路問題

オペレーションズ・リサーチ

NP

P

全組み合わせ問題

Page 40: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

NP問題

NP: 非決定的多項式可解な問題

都合良く選択肢を選ぶと、問題サイズの多項式オーダの手数で解が得られる

工学的に有用な問題が多数含まれる

負ループを含む 短経路問題

セールスマンの巡回問題

タスク・スケジューリング問題 など

Page 41: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

セールスマンの巡回問題

問題の定義「N個の都市を順に訪問するための旅費が

小になる訪問順を求めよ」

都市間の旅費は非負

短経路( 小費用)を求める問題

一見すると 短経路問題として解けそう?

すべての訪問順を列挙して 小費用の順路を求める方法しか知られていない ⇒ )!(NO

Page 42: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

NP問題とP問題

NP問題の解には、今のところ非多項式オーダの手数が必要

多項式オーダの解法が存在しないことは証明されていない

もしかするとNP=Pかもしれない

NP問題のどれか1つについて多項式オーダの解法が見つかればNP=P

すべてのNP問題が多項式オーダで解ける!

Page 43: プログラミング言語I 第10回 最短経路問題 · プログラミング言語i 第10回 最短経路問題 埼玉大学工学部 電気電子システム工学科 伊藤和人

Copyright © 2008 Kazuhito Ito

まとめ

問題定式化とグラフ

短経路問題

効率よい解法

ダイクストラ法

Bellman-Ford法

リスト構造

組み合わせ 適化問題とNP