dijkstra最短路 链式前向星+堆优化

#include <bits/stdc++.h>
using namespace std;
// 测试:https://www.luogu.com.cn/problem/P4779

/*
要求:求s到其他点的最短路径
1. dis[v] 表示s到v点的最短距离
2. 每次找出dis的最小值的点(堆优化,<距离,点>堆顶为距离最小)
3. 从这个点出发走到其他点,更新dis
*/

const int N = 2e5 + 10;
const int MAXINT = 2147483647;

// 存储最小距离和是否最小
int dis[N], check[N];

/*
1. head 数组,head[i] 表示 i 点的头边
2. next 数组,next[i] 表示第 i 条边的下一条边的编号
3. to 数组,to[i] 表示第 i 条边去往的点
4. cnt,表示边的编号
*/
int Head[N], Next[N], To[N];
int Weight[N];
int cnt = 1;

void addEdge(int u, int v, int w)
{
    // 注意此时cnt编号为新边的编号,cnt从1开始
    Next[cnt] = Head[u]; // 把新边插在Head和Head[u]之间
    To[cnt] = v;         // 新边指向v点
    Weight[cnt] = w;
    Head[u] = cnt++; // u点的头边是cnt,然后cnt++
}

// 顶点个数 路径数 和起始点
int n, m, s;

int main()
{
    cin >> n >> m >> s;
    // 初始化dis为无穷大
    for (int i = 1; i <= n; i++)
    {
        dis[i] = MAXINT;
        check[i] = 0;
    }
    // 读入数据,初始化邻接矩阵
    for (int i = 1; i <= m; i++)
    {
        int a, b, c;
        cin >> a >> b >> c;
        addEdge(a, b, c);
    }

    /*开始处理*/
    // 设置起点的距离
    dis[s] = 0;
    // 遍历所有点

    // 堆优化
    priority_queue<pair<int, int>, vector<pair<int, int>>, greater<pair<int, int>>> pq;
    pq.push({0, s});
    while (pq.size())
    {
        // 找出最小的dis,然后从最小的开始处理
        int minn = pq.top().first, mini = pq.top().second; // 分别是最小dis和最小dis的下标
        pq.pop();

        if (check[mini])
            continue;
        // 把找到的最小值标记
        check[mini] = 1;

        // 在找到最小的值后,从该点出发
        for (int e = Head[mini]; e > 0; e = Next[e])
        {
            int v = To[e];
            // 如果这maxi和j相互连接,那么进行比较
            // 判断dis[j]和dis[maxi]+graph[][]的距离
            if (Weight[e] + minn < dis[v])
            {
                dis[v] = Weight[e] + minn;
                pq.push({dis[v], v});
            }
        }
    }

    for (int i = 1; i <= n; i++)
        cout << dis[i] << " ";
    cout << endl;
    return 0;
}
posted @ 2024-05-14 13:43  lulaalu  阅读(42)  评论(0)    收藏  举报