最短路-Dijkstra算法

Dijkstra算法是一种用于寻找图中单源最短路径的算法,不适用于存在负权重的边。该算法从源点开始,逐步将最近的节点加入已找到最短路径的集合中。其时间复杂度为O(n^2)。初始时,所有点的最短路径设为无穷大,源点设为0。每次选取当前未访问节点中距离源点最近的一个,更新其相邻节点的最短路径。这个过程重复直至所有节点都被处理。HDU 2544题目可作为实践应用的例子。

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

Dijkstra最短路算法

与Floyd算法(求任意两点间最短路)不同,Dijkstra可以求单源最短路径(不含负权)

算法思想:从源点开始逐个把距离源点最近的点,加入到源点可以最快到达的集合中,直到所有的点都加入进来。

时间复杂度O(n^2)

1.初始化。令所有点最短路径dist[i]=MAX,访问标记visit[i]=0

2.令源点dist[s]=0,为了操作的一致性,保证循环第一次选中源点

3.每次选一个节点,总共选择n次

3.1遍历dist[]数组,选最小的那个u加入到可最快到达集合中(第一次是u==s)并记录节点编号   

3.2 遍历u的所有未被访问的邻接点j,如果dist[u]+Metrix[u][j]<dist[j],说明通过u到达j更近,则需修改dist[j]

int Dijkstra(int s,int t,int NV)//NV为图中节点个数,节点编号从1开始
{
    int u=s;
    for(int i=1;i<=NV;i++)
    {
        dist[i]=MAX;
        vist[i]=0;
    }
    dist[u]=0;//第一次确保dist[s]最小,保证第一个选中s
    for(int i=1;i<=NV;i++)
    {
        int min_value=MAX;
        for(int j=1;j<=NV;j++)//在dist[]中选中最小的节点u
        {
            if(vist[j]==0&&dist[j]<min_value)
            {
                min_value=dist[j];
                u=j;
            }
        }
        vist[u]=1;
        //cout<<u<<" ";
        for(int j=1;j<=NV;j++)//查看并更新u的未被访问的邻接点
        {
            if(vist[j]==0&&dist[u]+Metrix[u][j]<dist[j])
            {
                dist[j]=dist[u]+Metrix[u][j];
            }
        }
    }
    return dist[t];
}

 注意:内层循环第二个循环内for 与prim算法的区别

列题:http://acm.hdu.edu.cn/showproblem.php?pid=2544


#include <iostream>
#define N 105
#define MAX 0x03fffffff;
using namespace std;
int Metrix[N][N];
int dist[N];
int vist[N];
int Dijkstra(int u,int NV)
{
    for(int i=1;i<=NV;i++)
    {
        dist[i]=MAX;
        vist[i]=0;
    }
    dist[u]=0;
    for(int i=1;i<=NV;i++)
    {
        int min_value=MAX;
        for(int j=1;j<=NV;j++)
        {
            if(vist[j]==0&&dist[j]<min_value)
            {
                min_value=dist[j];
                u=j;
            }
        }
        vist[u]=1;
        //cout<<u<<" ";
        for(int j=1;j<=NV;j++)
        {
            if(vist[j]==0&&dist[u]+Metrix[u][j]<dist[j])
            {
                dist[j]=dist[u]+Metrix[u][j];
            }
        }
    }
    return dist[NV];
}
int main()
{
    int m,n;
    int s,t,c;
    while((cin>>n>>m)&&(n||m))
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(i==j)
                {
                    Metrix[i][j]=0;
                }
                else
                {
                    Metrix[i][j]=MAX;
                    Metrix[j][i]=MAX;
                }
            }
        }
        for(int i=0;i<m;i++)
        {
            cin>>s>>t>>c;
            Metrix[s][t]=c;
            Metrix[t][s]=c;
        }
        cout<<Dijkstra(1,n)<<endl;
    }
    return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值