单源最短路算法Dijkstra
思路:每次寻找距离原点最近的点,通过该点松弛其他的点。
变量
m为边数,n为点数,dis[i]表示从1到点i的最短路径,book[i]表示点1到点i的路程是否最短,e为邻接矩阵,min和u之后才用到
int m, n, dis[N], book[N], e[N][N] min, u;
初始化+读入
读入n,m不再赘述
    scanf("%d %d", &n, &m);
一开始所有点都初始化为INF表示互不相连,i==j时自己连向自己,路程为0
   //初始化点i到j的距离为INF 自己到自己为0
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            if (i == j)
                e[i][j] = 0;
            else
                e[i][j] = INF;
        }
读入m条边 将数组e[a][b]的值赋值为权重c
    //读入
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        e[a][b] = c;
    }
因为e表示i到j的路程,dis表示从1到i的路程。
所以dis[i]初始化时等于e[1][i]
就是 从1到i的路程 (dis[i]) 等于 从1到 i (e[1][i]) 的路程 翻译成人话就是完全一样的东西,但仅仅是初始化时
book数组0表示还未松弛,1表示松弛完毕即已经找到最短路径
book[1]表示点1到点1是否需要松弛,当然不用啊,所以book[1]=1;
    //初始化dis[i]为1到i的距离  顺便初始化book 1为已确定最短路 0为待松弛
    for (int i = 1; i <= n; i++) {
        dis[i] = e[1][i];
        book[i] = 0;//初始化所有点为待松弛
    }
    book[1] = 1;//自己不用松弛
算法思路
dijkstra主要分3步
1.找到目前距离1号点最近的点,记作点u
2.遍历点u联通的所有点,记作点v
3.如果从1直接到点v的距离 大于 从点1到点u再到点v的距离,更新1到v的最短距离

如图 点1直接到点v的距离比从点u中转要大,所以要松弛点1到v的距离
算法具体代码实现
1.找距离点1最近的点
先将最小值赋值为INF
min = INF;
先遍历所有点,如果这个点待松弛,即book[j]==0,并且是最小值,那我们更新最小值,然后用变量把最小点的编号记下来
        for (int j = 1; j <= n; j++) {            //遍历
            if (book[j] == 0 && dis[j] < min) {    //如果此点待松弛并且点1到点j的距离小于min
                min = dis[j];                    //更新min
                u = j;                            //更新离1号点最近的点的编号
            }
        }
2.遍历所有与点u相连的点
一个for循环搞定
for (int v = 1; v <= n; v++)
3.核心语句 松弛点1到点v的距离
        /****    如果目前离点1最近的点与点i联通(权小于INF)  并且  点1到点i的距离大于<点1到u再从u到i的距离>   ****/
            if (e[u][v]<INF && dis[v] > dis[u] + e[u][v]) {
                dis[v] = dis[u] + e[u][v];        //更新最小距离
            }
如果u和v不相连,那e[u][v]就是INF,下面这句是判断u和v是否相连
e[u][v]<INF
dis[v]表示1到点v的距离 下图1>>>v,dis[u]表示点1到点u的距离 下图1>>>u,e[u][v]表示点u到v的距离下图u>>v
dis[v] > dis[u] + e[u][v]

所以这句话就是比较 1>>>v 和 1>>>u>>>v 那个小 ,我们求的是最短路,当然那个短要哪个。
dis[v] = dis[u] + e[u][v]; //更新最小距离
更新点 1>>>v 的值为 1>>>u>>>v
所以上面的代码翻译过来就是:
如果点u与点v相连,并且从点u中转比直接1到v要短。
更新点1到v的距离为从点u中转的距离(之前要么是INF,即不相连,要么是点1直接到v的距离)
            if (e[u][v]<INF && dis[v] > dis[u] + e[u][v]) {
                dis[v] = dis[u] + e[u][v];        //更新最小距离
            }
然后这个点松弛完了我们要将他的book从0(未松弛)变成1(松弛完毕)
book[u] = 1;
以上是松弛了一个点,但我们要松弛所有点,就是找到所有点的最短路径。
我们一共有n个点,除去点1还有n-1个点,所以在外面套一个for循环就OK了
for (int a = 1; a <= n - 1; a++)//a在这就是个计数的
dijkstra算法代码如下
void dijksrat() {    
    for (int a = 1; a <= n - 1; a++) { //第一步
        min = INF;
        for (int j = 1; j <= n; j++) {
            if (book[j] == 0 && dis[j] < min) {   
                min = dis[j];                
                u = j;                           
            }
        }
        for (int v = 1; v <= n; v++) {           //第二步
       
            if (e[u][v]<INF && dis[v] > dis[u] + e[u][v]) {//第三步
                dis[v] = dis[u] + e[u][v];  
            }
        }
     book[u] = 1;//标记
    }
    return;
}
单源最短路算法完整代码:
//关闭VS安全检查#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <cstdio>
#define N 1001
#define INF 23333
int m, dis[N], book[N], e[N][N], n, min, u;
void dijksrat() {    
    for (int a = 1; a <= n - 1; a++) {            //将边松弛n-1次即可得到最短路径
        min = INF;
        //找到1号点最近的点
        for (int j = 1; j <= n; j++) {            //遍历
            if (book[j] == 0 && dis[j] < min) {    //如果此点待松弛并且点1到点j的距离小于min
                min = dis[j];                    //更新min
                u = j;                            //更新离1号点最近的点的编号
            }
        }
        for (int v = 1; v <= n; v++) {            //遍历所有点
        /****    如果目前离点1最近的点与点i联通(权小于INF)  并且  点1到点i的距离大于<点1到u再从u到i的距离>   ****/
            if (e[u][v]<INF && dis[v] > dis[u] + e[u][v]) {
                dis[v] = dis[u] + e[u][v];        //更新最小距离
            }
        }     book[u] = 1;
    }
    return;
}
int main()
{    
    scanf("%d %d", &n, &m);
    //初始化点i到j的距离为INF 自己到自己为0
    for (int i = 1; i <= n; i++)
        for (int j = 1; j <= n; j++) {
            if (i == j)
                e[i][j] = 0;
            else
                e[i][j] = INF;
        }
    //读入
    for (int i = 1; i <= m; i++) {
        int a, b, c;
        scanf("%d%d%d", &a, &b, &c);
        e[a][b] = c;
    }
    //初始化dis[i]为1到i的距离  顺便初始化book 1为已确定最短路 0为待松弛
    for (int i = 1; i <= n; i++) {
        dis[i] = e[1][i];
        book[i] = 0;//初始化所有点为待松弛
    }
    book[1] = 1;//自己不用松弛
    dijksrat();
    for (int i = 1; i <= n; i++)
        printf("%3d", dis[i]);
    return 0;
}