Dijkstra FORMCM

Dijkstra 算法

    date: 2018/2/2
    author:pprp
    theme:Dijstra

简述

  • 辅助空间

    • vis数组:记录是否已经判断过
      • dis数组:记录指定原点到其他点的距离
      • mp二维数组:记录图的信息
  • 初始化

    • vis数组:设置为false
    • dis:设置为原点为0,其余为inf
    • mp:初始化为inf
    • 最重要的初始化是将dis[i]=mp[st][i]
  • 遍历操作

    • 每次找到dis中最小且没有被访问过的点,将其作为起始点
    • 进行松弛操作
  • 得到结果

形象化记忆

以起始点为中心向外层层扩展,直到扩展到终点为止。
参考

程序源码

  • C++实现
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>

using namespace std;

const int inf = 0x3f3f3f3f;
const int maxn = 1000;
const int m = 6; //顶点个数
const int n = 8; //边的个数

int mp[maxn][maxn];
int dis[maxn];
bool vis[maxn];

void dijkstra(int st){

    for(int i = 1 ;i <= m; i++ )
        dis[i] = mp[st][i];
    vis[st] = 1;
    dis[st] = 0;
    for(int i  = 1; i <= m ; i++){
        int Min = inf;
        int rec = -1;
        for(int j = 1; j <= m ; j++){
            if(!vis[j] && Min > dis[j])
            {
                rec = j;
                Min = dis[j];
            }
        }
        if(rec == -1)return ;
        vis[rec] = 1;
        for(int j = 1; j <= m ; j++){
            if(!vis[j] && mp[rec][j] != inf && dis[rec]+mp[rec][j] < dis[j]){
                dis[j] = dis[rec] + mp[rec][j];
            }
        }
    }
}


int main(){
    for(int i = 0 ; i < maxn ; i++)
    {
        for(int j = 0 ; j < maxn ; j++)
        {
            mp[i][j] = inf;
        }
    }
    int x, y , z;
    memset(vis,0,sizeof vis);
    for(int i = 0; i < n ; i++){
        cin >> x >> y >> z;
        mp[x][y] = z;
    }
    dijkstra(1);
    for(int i = 1; i <= m ;i++)
        cout << dis[i] << " ";
    cout << endl;


    return 0;
}

  • Matlab实现
clc,clear all
a=zeros(6);
a(1,2)=50;a(1,4)=40;a(1,5)=25;a(1,6)=10;
a(2,3)=15;a(2,4)=20;a(2,6)=25;
a(3,4)=10;a(3,5)=20;
a(4,5)=10;a(4,6)=25;
a(5,6)=55;

a=a+a'

a(find(a==0))=inf %将a=0的数全部替换为无强大
pb(1:length(a))=0;pb(1)=1;  %当一个点已经求出到原点的最短距离时,其下标i对应的pb(i)赋1
index1=1; %存放存入S集合的顺序
index2=ones(1,length(a)); %存放始点到第i点最短通路中第i顶点前一顶点的序号
d(1:length(a))=inf;d(1)=0;  %存放由始点到第i点最短通路的值
temp=1;  %temp表示c1,算c1到其它点的最短路。

while sum(pb)<length(a)  %看是否所有的点都标记为P标号
tb=find(pb==0); %找到标号为0的所有点,即找到还没有存入S的点
d(tb)=min(d(tb),d(temp)+a(temp,tb));%计算标号为0的点的最短路,或者是从原点直接到这个点,又或者是原点经过r1,间接到达这个点
tmpb=find(d(tb)==min(d(tb)));  %求d[tb]序列最小值的下标
temp=tb(tmpb(1));%可能有多条路径同时到达最小值,却其中一个,temp也从原点变为下一个点
pb(temp)=1;%找到最小路径的表对应的pb(i)=1
index1=[index1,temp];  %存放存入S集合的顺序
temp2=find(d(index1)==d(temp)-a(temp,index1));
index2(temp)=index1(temp2(1)); %记录标号索引
end
d, index1, index2

测试数据

0 5 100
0 4 30
1 2 5
0 2 10
2 3 50
3 5 10
4 3 20
4 5 60

原文地址:https://www.cnblogs.com/pprp/p/8406136.html