dijkstra算法

10 篇文章 0 订阅
10 篇文章 0 订阅

算法描述

dijkstra算法的步骤如下:

  1. 初始化dist[1]=0,其余节点为无穷大
  2. 找到一个不在最短集合内的最小节点x,将其加入最短集合队列
  3. 扫描节点x的所有出边(x,y,z),若dist[y]>dist[x]+z,则使用dist[y]=z来更新dist[y]
  4. 重复上述2~3步骤,直到所有节点都被标记

第一种写法(邻接矩阵存储)

const int N=510,INF=1e9;
int g[N][N];  // g[i][j] 存的是第i点到第j点的距离
int dis[N];   // dis[i] 存的是第一个点到第i点的距离
int n,m;  // n为顶点数,m为边数
bool st[N];  // st[]存已经是最短路径的点

void dijkstra(){   
    memset(dis,0x3f,sizeof dis);  // dis 初始化为0x3f3f3f3f (任意一个取不到的值即可)
    dis[1]=0;
    for(int i=1;i<=n;i++){  // 遍历n次
        int t=0;   // 找到当前st[]=false 的最小值的顶点
        for(int j=1;j<=n;j++){
            if(!st[j]&& dis[j]<dis[t])
                t=j;
        }
        st[t]=1;   // 将当前顶点加入st[]
        for(int j=1;j<=n;j++){   // 更新dis
            dis[j]=min(dis[j],dis[t]+g[t][j]); // 
        }
    }
    // dis[i] 存的是第一个点到第i个点的距离
    // 若为0x3f3f3f3f,则不存在路径
}
算法评价

该算法的时间复杂度为O(n^2),适合存储稠密图,主要用于寻找最小边,每次复杂度为O(n)n 次就为O(N^2),这里我们可以使用小根堆在O(logn)获取最小值,并从堆中删除,最后在O(mlogn)时间内来实现Dijkstra算法

第二种写法(邻接表存储)

const int N=1.5e5+10;
typedef pair<int,int>PII;
int h[N],e[N],ne[N],w[N],idx; 
int n,m;
int dis[N];
bool st[N];

void add(int a,int b,int c){
    e[idx]=b;
    w[idx]=c;
    ne[idx]=h[a];
    h[a]=idx++;
}

void dijkstra(){
    memset(dis,0x3f,sizeof dis);
    dis[1]=0;
    priority_queue<PII,vector<PII>,greater<PII>>heap;
    heap.push({0,1});
    while(heap.size()){
        PII t=heap.top();
        heap.pop();
        int distance=t.first,ver=t.second;
        if(st[ver])continue;
        st[ver]=true;
        for(int i=h[ver];i!=-1;i=ne[i]){
            int j=e[i];  // 边
            if(dis[j]>dis[ver]+w[i]){
                dis[j]=dis[ver]+w[i]; //
                heap.push({dis[j],j});
            }
        }
    }
}
算法评价

该算法的时间复杂度为O(mlogn),适合存储稀疏图,这里的小根堆可用priority_queue来实现,默认为大根堆,若想改成小根堆,第一种是代码中的写法,第二种是插入相反数就成了小根堆

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值