最短路:Dijkstra

16 篇文章 0 订阅
9 篇文章 0 订阅
本文探讨了Dijkstra算法在无负权边图中最短路径查找的原理,包括使用邻接表和邻接矩阵的不同数据结构,以及利用set和priority_queue进行的时间复杂度优化。详细介绍了代码实现并分析了各自的优势和适用场景。
摘要由CSDN通过智能技术生成

Dijkstra

无负权边图中的最短路

维护一个顶点集合C,满足对于所有集合C的顶点x,我们都已经找到起点到x的最短路,此时dist(x)记录的就是最终最短路的长度。

将C设置为空,将S的距离为0,其余顶点的距离设置为无穷大。

在每一轮中,将离起点最近的(dist最小)的还不在C中的顶点加入C,并且用这个点连出去的边通过松弛操作尝试更新其他点的dist。

当T加入C时或者没有新的点加入C时结束。

时间复杂度 O ( n 2 + m ) O(n^2+m) O(n2+m)

邻接表

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
vector<PII> edge[N];
int n, m, dist[N];
bool b[N];

int Dijkstra(int s, int t)
{
    memset(b, false, sizeof b);
    memset(dist, 127, sizeof dist);
    dist[s] = 0;
    while (true)
    {
        int x = -1;
        for (int i = 1; i <= n; i++)
            if (!b[i] && dist[i] < 1 << 30)
                if (x == -1 || dist[i] < dist[x])
                    x = i;
        if (x == t || x == -1)
            break;
        b[x] = true;
        for (auto i : edge[x])
            dist[i.first] = min(dist[i.first], dist[x] + i.second);
    }
    if (dist[t] < 1 << 30)
        return dist[t];
    else
        return -1;
}

邻接矩阵

int g[N][N];
int dist[N];
bool st[N];

int dijkstra(int s, int t)
{
    memset(dist, 0x3f, sizeof dist);
    dist[s] = 0;

    for (int i = 0; i < n - 1; i++)
    {
        int x = -1;
        for (int j = 1; j <= n; j++)
            if (!st[j] && (x == -1 || dist[x] > dist[j]))
                x = j;
        for (int j = 1; j <= n; j++)
            dist[j] = min(dist[j], dist[x] + g[x][j]);
        st[x] = true;
    }

    if (dist[t] == 0x3f3f3f3f)
        return -1;
    return dist[t];
}

Dijkstra优化

set优化

时间复杂度: O ( ( n + m ) l o g n ) O((n+m)log n) O(n+mlogn)

typedef pair<int, int> PII;
const int N = 5e3 + 10;
const int M = 1e4 + 10;
set<PII> q;
vector<PII> edge[N];
int n, m, dist[N];

int Dijkstra(int s, int t)
{
    memset(dist, 127, sizeof dist);
    dist[s] = 0;
    q.clear();
    for (int i = 1; i <= n; i++)
        q.insert({dist[i], i});
    while (!q.empty())
    {
        int x = q.begin()->second;
        q.erase(q.begin());
        if (x == t || dist[x] > 1 << 30)
            break;
        for (auto i : edge[x])
        {
            if (dist[x] + i.second < dist[i.first])
            {
                q.erase({dist[i.first], i.first});
                dist[i.first] = dist[x] + i.second;
                q.insert({dist[i.first], i.first});
            }
        }
    }
    if (dist[t] < 1 << 30)
        return dist[t];
    else
        return -1;
}

priority_queue优化

时间复杂度: O ( m l o g n ) O(mlog n) O(mlogn)

typedef pair<int, int> PII;

vector<PII> edge[N];
int dist[N]; 
bool st[N];  

int Dijkstra(int s, int t)
{
    memset(dist, 0x3f, sizeof dist);
    memset(st, false, sizeof st);
    dist[s] = 0;
    priority_queue<PII, vector<PII>, greater<PII>> heap;
    heap.push({0, s});

    while (heap.size())
    {
        auto t = heap.top();
        heap.pop();
        
        int ver = t.second, distance = t.first;

        if (st[ver])
            continue;
        st[ver] = true;

        for (auto i : edge[ver])
        {
            if (dist[i.first] > distance + i.second)
            {
                dist[i.first] = distance + i.second;
                heap.push({dist[i.first], i.first});
            }
        }
    }

    if (dist[t] == 0x3f3f3f3f)
        return -1;
    return dist[t];
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值