データ構造 - に示すDjikstraの最短経路アルゴリズム(ダイクストラ)

A. Djikstra定義されたアルゴリズム

  1. 形式:単一始点最短経路問題のために、すなわち、グラフG、および出発点の、各頂点によって最短距離アルゴリズムを与えられました。
  2. 基本思想:図G(V、E)の集合Sを設定し、記憶する頂点が訪問し、次いで収集から開始点S頂点uの最小値VS、収集及びS.へのアクセスのそれぞれからの最短距離を選択されています その後、開始点との間の最短距離を最適化し、中間点とU頂点行い、全てのuは、頂点vから到達することができます。この動作が行わN(頂点の数)倍です。
  3. 伪代码:
//G为图, 一般设置为全局变量,数组d为源点到达各点的最短路径长度,s为起点
Djikstra(G, d[], s){
    初始化
    for(循环n次){
        u = 是d[u]最小的还未被访问的顶点的标号
        记u已被访问
        for(从u出发能到达的所有顶点v){
            if(v未被访问&&以U为中介使得s到顶点v的最短距离d[v]更优){
                优化d[v]
            }
        }
    }
}

第二に、特定の実装

1.隣接行列バージョン
const int MAXV = 1000;//最大顶点数
const int INF = 10000000000;//设INF为一个很大数

//适用于点数不大的情况
int n, G[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV];

void Dijkstra(int s){
    fill(d, d+MAXV, INF);
    d[s] = 0;
    for(int i = 0; i < n; i++){
        int u = -1. MIN = INF;//u使d[u]最小, MIN存放该最小d[u]
        for(int j = 0; j < n; j++){
            if(vis[j] == false && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        //找不到小于INF的d[u],说明剩下的顶点与s不连通
        if(u == -1) return;
        vis[u] = true;//标记u为已访问
        for(int v = 0; v < n; v++){
            //如果v未访问&&u能够到达v&&以u为中介点可以使d[v]更优
            if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
                d[v] = d[u] + G[u][v];//优化d[v]
            }
        }
    }
}
2.隣接リストバージョン
struct node{
    int v, dis;//v为边的目标顶点,dis为边权
};

vector<node> Adj[MAXV];
int n;
int d[MAXn];
bool vis[MAXV] = {false};

void Dijkstra(int s){
    fill(d, d+MAXV, INF);
    d[s] = 0;
    for(int i = 0; i < n; i++){
        int u = -1, MIN = INF;
        for(int j = 0; j < n; j++){
            if(vis[j] == false && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        if(u == -1) return;
        vis[u] = true;
        //只有这个部分与邻接矩阵自而发不同
        for(int j = 0; j < Adj[u].size(); j++){
            int v = Adj[u][j].v//通过邻接表直接获得u能够到达的v
            if(vis[v] == false && d[u] + Adj[u][j].dis < d[v]){
                d[v] = d[u] + Adj[u][j].dis;
            }
        }
    }
}
3.(上記に基づいて)の最短経路を見つけるための方法
  • タイトルは無向グラフが与えられた場合、隣接行列が同時に両側で同じ重量を追加することができれば、それは、独自の隣接リストと隣接行列に応じて変更することができ、隣接テーブル、それがそのように使用される一backある場合、また入力を交換しながら。
<1>実施例隣接行列
const int MAXV = 1000;//最大顶点数
const int INF = 10000000000;//设INF为一个很大数

//适用于点数不大的情况
int n, G[MAXV][MAXV];
int d[MAXV];
bool vis[MAXV];
int pre[MAXV];//表示从起点到顶点v的最短路径上v的前一个顶点(新添加)
void Dijkstra(int s){
    fill(d, d+MAXV, INF);
    d[s] = 0;
    for(int i = 0; i < n; i++){
        int u = -1. MIN = INF;//u使d[u]最小, MIN存放该最小d[u]
        for(int j = 0; j < n; j++){
            if(vis[j] == false && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        //找不到小于INF的d[u],说明剩下的顶点与s不连通
        if(u == -1) return;
        vis[u] = true;//标记u为已访问
        for(int v = 0; v < n; v++){
            //如果v未访问&&u能够到达v&&以u为中介点可以使d[v]更优
            if(vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
                d[v] = d[u] + G[u][v];//优化d[v]
                //就是在这里改变,添加了一条语句
                pre[v] = u;//新添加
            }
        }
    }
}

//如何打印,就是递归打印
void dfs(int s, int v){
    if(v == s){
        printf("%d\n", s);
        return;
    }
    dfs(s, pre[v]);
    printf("%d\n", v);
}
4.他の場合に起こる、すなわち、追加条件
  • 最初の最短パス条件に加えて表示さは、複数のパス場合、他の条件があってもよいです
  • 各側は、右側(支出)を追加します。
  • 各ポイントは、(例えば、各都市が受け取ることができる用品のような)点を右に追加し、
  • 直接どのように多くの最短パスを尋ねました。
<1>新しい右側。右側には、例えば、変更される最終的な判断であり、支出を追加するために、残りの部分は変更せずにいました
        for(int v = 0; v < n; v++){
            //如果v未访问&&u能够到达v&&以u为中介点可以使d[v]更优
            if(vis[v] == false && G[u][v] != INF){
                if(d[u] + G[u][v] < d[v]){
                     d[v] = d[u] + G[u][v];//优化d[v]
                     c[v] = c[u] + cost[u][v];
                }else if(d[u] + G[u][v] == d[v] && c[u] + cost[u][v] < c[v]){
                    c[v] = c[u] + cost[u][v];
                }
            }
        }
<2>都市に収集することができる新たな材料の代わりに右の点に正しいポイントを追加するために、例えば、Uは重量[U]を有する材料内の都市の数を表し、そして開始点Sとしてそれを作るために、] [配列Wを追加します最大材料Wに到達するために、[U]はuの頂点収集することができます。
        for(int v = 0; v < n; v++){
            //如果v未访问&&u能够到达v&&以u为中介点可以使d[v]更优
            if(vis[v] == false && G[u][v] != INF){
                if(d[u] + G[u][v] < d[v]){
                     d[v] = d[u] + G[u][v];//优化d[v]
                     w[v] = w[u] + weight[v];
                }else if(d[u] + G[u][v] == d[v] && w[u] + weight[v] > w[v]){
                    w[v] = w[u] + weight[v];
                }
            }
        }
最短経路の<3>必要な数。= 1 [S]配列NUM []、初期NUMを追加する必要があるだけ、残りは[U] = 0 NUMです。
        for(int v = 0; v < n; v++){
            //如果v未访问&&u能够到达v&&以u为中介点可以使d[v]更优
            if(vis[v] == false && G[u][v] != INF){
                if(d[u] + G[u][v] < d[v]){
                     d[v] = d[u] + G[u][v];//优化d[v]
                     num[v] = num[u];
                }else if(d[u] + G[u][v] == d[v]){
                    num[v] += num[u];
                }
            }
        }

おすすめ

転載: www.cnblogs.com/tsruixi/p/12380430.html
おすすめ