ダイクストラ法ー最短経路問題


隣接行列と、始点が与えられたとき、残りの頂点への最短経路を求める。C言語で実装。計算量は $O(V^2)$

イメージはこちらのサイトを参考にした。http://nw.tsuda.ac.jp/lec/dijkstra/

#include <stdio.h>
/*
Dijkstra
Given adjecent matrix,
Calculate the shortest path from start point to each point.
*/
#define N 8
#define M << 30
int edge[N][N]= {{0,1,7,2,M,M,M,M},
                {1,0,M,M,2,4,M,M},
                {7,M,0,M,M,2,3,M},
                {2,M,M,0,M,M,5,M},
                {M,2,M,M,0,1,M,M},
                {M,4,2,M,1,0,M,6},
                {M,M,3,5,M,M,0,2},
                {M,M,M,M,M,6,2,0}};

int min(int a,int b){
    return a < b ? a : b;
}
int main(void){
    int start = 0;
    int confirmed[N];
    int cost[N];
    int minc, ref;
    int i,j;
    for(i = 0; i < N; i++){
        confirmed[i]=0;
        cost[i]=M; 
    }
    cost[start] = 0;
    for(i=0;i<N;i++){
        // find min cost node from unconfirmed nodes
        minc = M;
        for(j=0;j<N;j++){
            if(!confirmed[j] && cost[j] < minc){
                minc = cost[j];
                ref = j;
            }
        }
        if(minc==M) {
            printf("graph not connected"); exit(1);
        }
        for(j=0;j<N;j++){
            if (edge[ref][j] < M){ //if connected nodes
                cost[j] = min(cost[j], cost[ref] + edge[ref][j]); // update if less cost via ref               
            }
        }
        confirmed[ref] = 1;
    }
    printf("shortest path from %d\n",start);
    for(i=0;i<N;i++){
        printf("%d: %d\n",i, cost[i]);
    }
}
# result
$ ./a.out
shortest path from 0
0: 0
1: 1
2: 6
3: 2
4: 3
5: 4
6: 7
7: 9

隣接リストで辺が与えられている場合、つながっている頂点を求める計算量がそのままEになる。優先度付きキューを使えば最小値を取り出す操作は log V になる。合わせると、$O((E+V)\log V)$となり、高速化できる。