*补*dij板子重制版

#include <bits/stdc++.h>
using namespace std;

int n, m;
int dis[10010];  // 存储起点到各点的最短距离
int u[10010], v[10010], w[10010];  // 边的起点、终点、权重
int first[10010], nxt[10010];  // 邻接表:first[u]是u的第一条边索引,nxt[i]是边i的下一条边索引
struct edge {
    int to;  // 目标节点
    int w;   // 距离(用于优先队列排序)
};
int vis[10010];  // 标记节点是否已确定最短路径

// 优先队列重载小于号,实现小根堆(按距离从小到大)
bool operator<(edge a, edge b) {
    return a.w > b.w;
}

void dijkstra(int start) {
    dis[start] = 0;
    priority_queue<edge> pq;
    pq.push({start, 0});  // 起点入队

    while (!pq.empty()) {
        edge U = pq.top();  // 取出当前距离最小的节点
        pq.pop();

        int u_node = U.to;  // 当前处理的节点
        if (vis[u_node]) continue;  // 已确定最短路径,跳过
        vis[u_node] = 1;  // 标记为已确定

        // 遍历当前节点的所有邻接边(邻接表遍历)
        int k = first[u_node];  // 第一条边的索引
        while (k != -1) {  // 遍历所有边,直到没有下一条边
            int v_node = v[k];  // 边的终点
            // 松弛操作:如果通过当前节点到v_node的路径更短
            if (dis[v_node] > dis[u_node] + w[k]) {
                dis[v_node] = dis[u_node] + w[k];  // 更新距离
                pq.push({v_node, dis[v_node]});  // 新距离入队
            }
            k = nxt[k];  // 下一条边
        }
    }
}

int main() {
    cin >> n >> m;

    // 初始化邻接表:所有节点的第一条边初始化为-1(无)
    memset(first, -1, sizeof(first));

    // 读入m条边,构建邻接表
    for (int i = 1; i <= m; ++i) {
        cin >> u[i] >> v[i] >> w[i];
        nxt[i] = first[u[i]];  // 新边的下一条是原第一条边
        first[u[i]] = i;       // 更新第一条边为当前边
    }

    // 初始化距离数组:起点外的节点距离设为无穷大
    memset(dis, 0x3f, sizeof(dis));

    int start;
    cin >> start;

    dijkstra(start);

    // 输出起点到各节点的最短距离
    for (int i = 1; i <= n; ++i) {
        // 若距离仍为无穷大,说明不可达,可输出特定符号(这里保持原值)
        cout << dis[i] << ' ';
    }

    return 0;
}
posted @ 2025-09-22 16:36  shuxin5  阅读(8)  评论(0)    收藏  举报