最短路径

  今天来介绍单源最短路径。所谓单源最短路径,是指在一个有向图中,从一个源点s出发,分别求出到其他各点的最短路径。我们采用迪杰斯特拉算法来实现单源最短路径。值得注意的是,迪杰斯特拉算法和prim算法很相似。迪杰斯特拉属于一种贪心思想的运用,在该算法中,图中各个节点被分为最短路树节点和非最短路树节点。

  迪杰斯特拉算法的步骤如下:

  1、使用一个数组d记录各点到源点s的距离,初始化距离数组为无穷大:(1 << 31)- 1。

  2、确定某个源点s,将源点s加入到最短路树中,更新源点d[s] = 0。

  3、以新加入最短路树的点now为顶点,更新所有与now直接相连的点到源点s的距离,也就是更新d数组。

  4、在最短路树节点中找到离源点s最近的点now,将now加入到最短路树中。

  5、重复步骤3、4直到完成。

  下面为实现代码:

#include <iostream>
#include <cstdio>
using namespace std;
const int MAXN = 10001;
const int MAXM = 500001;
const int INF = (1 << 31) - 1;

struct Line {
    int p;
    int v;
    int next;
};

struct Node {
    int d;
    bool book;
};

Node node[MAXN];
Line line[MAXM];
int h[MAXN];
int n, m, s, x, y, v, now;

void add(int x, int y, int v, int lID) {
    line[lID].p = y;
    line[lID].v = v;
    line[lID].next = h[x];
    h[x] = lID;
}
int find() {
    int p = 0;
    for(int i = 1; i <= n; i++) {
        if(!node[i].book) {
            if(p == 0 || node[p].d > node[i].d) {
                p = i;
            }
        }
    }
    return p;
}

void update(int now) {
    int k = h[now];  //与now节点相连的边的编号
    int p;
    while(k) {
        p = line[k].p;  //编号为k的边的长度
        if(!node[p].book) {
            if(node[p].d > line[k].v + node[now].d) {
                node[p].d = line[k].v + node[now].d;
            }
        }
        k = line[k].next;
    }
}

int main() {
    scanf("%d %d %d", &n, &m, &s);
    for(int i = 1; i <= m; i++) {
        scanf("%d %d %d", &x, &y, &v);
        add(x, y, v, i);
    }
    for(int i = 1; i <= n; i++) {
        node[i].book = false;
        node[i].d = INF;
    }
    node[s].book = true;
    node[s].d = 0;
    update(s);

    for(int i = 1; i < n; i++) {
        now = find();
        node[now].book = true;
        update(now);
    }
    for(int i = 1; i <= n; i++) {
        printf("%d ", node[i].d);
    }
    return 0;
}

   

  值得注意的是,在迪杰斯特拉算法中,有一步为寻找离源点s最近,在上面的代码中我们使用的是遍历每个节点来实现的,时间复杂度为O(N),实际上,我们在这这一步可以使用堆来进行优化。关于堆的内容,在我的下一篇博客中将进行讲解。

 

 

  圆满完成。

posted @ 2018-08-07 16:11  potato226  阅读(217)  评论(0编辑  收藏  举报