求最短路径

这篇博客介绍了单源最短路径问题,重点讲解了迪杰斯特拉算法的工作原理。迪杰斯特拉算法通过按路径长度递增的顺序寻找从源点到终点的最短路径,利用邻接矩阵表示有向图,并通过不断更新最短路径来逐步找到所有顶点的最短路径。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

单源最短路径

从源点到终点的路径可能存在三种情况:1. 没有路径 2. 只有一条路径 3. 有多条路径

迪杰斯特拉(Dijkstra)

思路:按照路径长度递增的次序从源点到终点的路径。

  1. 假设 G r a p h [ ] [ ] Graph[][] Graph[][]为有向网的邻接矩阵, S S S为已找到最短路径结点的集合,其初始状态为只含一个顶点,即源点。另设一个一维数组 D i s t [ n ] Dist[n] Dist[n],其中每个分量表示当前所找到的从源点出发(经过集合S中的顶点)到各个终点的最短路径长度。显然, D i s t Dist Dist的初值为:
    D i s t [ k ] = G r a p h [ i ] [ k ] Dist[k] = Graph[i][k] Dist[k]=Graph[i][k]1
  1. 选择 u u u,使得
    D i s t [ u ] = m i n { D i s t [ w ] ∣ w ∉ S , w ∈ V ( G ) } Dist[u] = min\{Dist[w] | w ∉ S, w∈ V(G)\} Dist[u]=min{Dist[w]w/S,wV(G)}
    u u u为目前找到的从源点出发的最短路径的结点。将这些结点 u u u并入集合 S S S
  2. 修改 D i s t Dist Dist数组中所有尚未找到最终路径的结点的对应分量值。如果 G r a p h [ u ] [ w ] Graph[u][w] Graph[u][w]为有限值,即从顶点 u u u到顶点 w w w有弧存在,并且
    D i s t [ u ] + G r a p h [ u ] [ w ] < D i s t [ w ] Dist[u]+Graph[u][w] < Dist[w] Dist[u]+Graph[u][w]<Dist[w]
    则令:
    D i s t [ w ] = D i s t [ u ] + G r a p h [ u ] [ w ] Dist[w] = Dist[u] + Graph[u][w] Dist[w]=Dist[u]+Graph[u][w]
  3. 重复上述(2)和(3)的操作n-1次,即可求得从源点到所有终点的最短路径。

思路:copy自这个博客

#include<iostream>
#include<vector>
using namespace std;

void Dijkstra(int n, int s, const vector<vector<int> > &G, vector<int> &prev) {
    // initilization
    vector<int> dist(n, INT_MAX);
    vector<bool> S(n, false); // 判断是否在S集合中
    for (int i = 0; i < n; i++) {
        dist[i] = G[s][i];
        if (dist[i] == INT_MAX) {
            prev[i] = 0;
        }
        else {
            prev[i] = s;    // 有值的结点前驱结点一定是源点
        }
    }
    S[s] = true;
    dist[s] = 0;

    // find next path for the shortest path
    int u; // next
    int value = INT_MAX;
    for (int i = 0; i < n; i++) {
        if (!S[i] && dist[i] < value) {
            value = dist[i];
            u = i;
        }
    }
    
    // update
    for (int i = 0; i < n; i++) {
        if (!S[i] && dist[i] != INT_MAX) {
            int temp = dist[u] + G[u][i];
            if (temp < dist[i]) {
                dist[i] = temp;
                prev[i] = u;
            }
        }
    }
}

void searchPath(const vector<int>& prev, int s, int e) {
    vector<int> rpath;
    rpath.push_back(e);
    int temp = prev[e];
    while (temp != s) {
        rpath.push_back(temp);
        temp = prev[temp];
    }
    rpath.push_back(s);

    for (auto it = rpath.rbegin(); it != rpath.rend();it++) {
        if (it != rpath.rend())
            cout << *it << "->";
        else
            cout << *it << endl;
    }
}


int main() {
    int n, edge;
    vector<int> prev;
    vector<vector<int>> G(n, vector<int>(n,INT_MAX)) ;
    int st, en, weight;

    // input
    cin >> n >> edge;

    // Graph
    for (int i = 0; i < edge; i++) {
        cin >> st >> en >> weight;
        G[st][en] = weight;
        G[en][st] = weight;
    }

    Dijkstra(n, st, G, prev);
    
    int T;
    cin >> T;
    while (T--) {
        int v;
        cin >> v;
        searchPath(prev, st, en);
    }
}

佛洛依德(略)


  1. i i i为源点在途中的序号 ↩︎

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值