问题 M: 算法7-15:迪杰斯特拉最短路径算法

题目描述

在带权有向图G中,给定一个源点v,求从v到G中的其余各顶点的最短路径问题,叫做单源点的最短路径问题。

在常用的单源点最短路径算法中,迪杰斯特拉算法是最为常用的一种,是一种按照路径长度递增的次序产生最短路径的算法。

可将迪杰斯特拉算法描述如下:

void Dijkstra() {
    for (int i = 0; i < n; i++) {
        dis[i] = inf;
        vis[i] = 0;
    }
    int i, j, k;
    for (dis[s] = 0, j = 0; j < n; j++) {
             for (k = - 1, i = 0; i < n; i++) {
                    if (!vis[i] && (k == - 1 || dis[i] < dis[k])) {
                k = i;
            }
        }
        for (vis[k] = 1, i = 0; i < n; i++) {
                    if (!vis[i] && dis[k] + mp[k][i] < dis[i]) {
                dis[i] = dis[k] + mp[k][i];
            }
        }
    }
}

在本题中,读入一个有向图的带权邻接矩阵(即数组表示),建立有向图并按照以上描述中的算法求出源点至每一个其它顶点的最短路径长度。

输入

输入的第一行包含2个正整数n和s,表示图中共有n个顶点,且源点为s。其中n不超过50,s小于n。

以后的n行中每行有n个用空格隔开的整数。对于第i行的第j个整数,如果大于0,则表示第i个顶点有指向第j个顶点的有向边,且权值为对应的整数值;如果这个整数为0,则表示没有i指向j的有向边。当i和j相等的时候,保证对应的整数为0。

输出

只有一行,共有n-1个整数,表示源点至其它每一个顶点的最短路径长度。如果不存在从源点至相应顶点的路径,输出-1。

请注意行尾输出换行。

样例输入复制

4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0

样例输出复制

6 4 7 

提示

在本题中,需要按照题目描述中的算法完成迪杰斯特拉算法,并在计算最短路径的过程中将每个顶点是否可达记录下来,直到求出每个可达顶点的最短路径之后,算法才能够结束。

迪杰斯特拉算法的特点是按照路径长度递增的顺序,依次添加下一条长度最短的边,从而不断构造出相应顶点的最短路径。

另外需要注意的是,在本题中为了更方便的表示顶点间的不可达状态,可以使用一个十分大的值作为标记。

#include <iostream>
 
using namespace std;
const int MAXN = 50, MAX = 9999;
int dis[MAXN][MAXN];
int n,m;
 
void Init() {
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            if (i != j&&dis[i][j]==0) dis[i][j] = MAX;
        }
    }
}
 
int main() {
    cin >> n >>m;
    m++;
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            cin >> dis[i][j];
        }
    }
    Init();
 
    for (int k = 1; k <= n; k++) {
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (dis[i][k] + dis[k][j] < dis[i][j]) {
                    dis[i][j] = dis[i][k] + dis[k][j];
                }
            }
        }
    }
 
        for (int j = 1; j <= n; j++) {
            if(dis[m][j]>=MAX) cout << -1 << " ";
            else if(j==m)continue;
            else cout << dis[m][j] << " ";
        }
        cout<<endl;
    return 0;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
贪心算法是一种常见的求解最短路径问题的方法,其中迪杰斯特拉算法是其中的一种实现方式。下面是迪杰斯特拉算法的具体步骤: 1. 创建一个大小为n的数组dist,用来记录源点到每个顶点的最短距离。初始化为无穷大,除了源点为0。 2. 创建一个大小为n的数组visited,记录每个顶点是否已经被访问过,初始值为false。 3. 在dist数组中找到未被访问过的距离最小的顶点v,并将visited[v]设置为true。 4. 对于顶点v的每个邻接点u,如果visited[u]为false,并且源点到u的距离比源点到v加上v到u的距离小,则更新dist[u]为这个更小的值。 5. 重复步骤3和步骤4,直到所有顶点都被访问过。 下面是迪杰斯特拉算法C++代码实现: ```c++ #include<iostream> #include<cstring> using namespace std; const int N = 1010; const int INF = 0x3f3f3f3f; int n,m,s,t; int g[N][N],dist[N]; bool visited[N]; void Dijkstra(int s){ memset(visited,false,sizeof(visited)); memset(dist,INF,sizeof(dist)); dist[s] = 0; for(int i=0;i<n;i++){ int v = -1; for(int j=0;j<n;j++){ if(!visited[j] && (v==-1 || dist[j]<dist[v])) v = j; } visited[v] = true; for(int u=0;u<n;u++){ if(!visited[u] && g[v][u]!=INF && dist[v]+g[v][u]<dist[u]){ dist[u] = dist[v]+g[v][u]; } } } } int main(){ cin>>n>>m>>s>>t; memset(g,INF,sizeof(g)); for(int i=0;i<m;i++){ int a,b,c; cin>>a>>b>>c; g[a][b] = g[b][a] = c; } Dijkstra(s); cout<<dist[t]<<endl; return 0; } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

VICTOR.杰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值