【PAT】最短路径算法Dijkstra模板总结

模板

#include <iostream>
#define MAX 9999999 // 表示边不存在,用INT32_MAX也可

using namespace std;
int main() {
   
    int N, M; // 顶点数,边数
    int C1, C2; // 起点,终点
    int A[N][N]; // 记录路径长度

	// 构造邻接矩阵
    cin >> N >> M >> C1 >> C2;
    fill_n(&A[0][0], N * N, MAX); // MAX表示不可达

    for (int i = 0; i < N; i++) cin >> V[i];

    int j, k; // 无向邻接图对称!
    for (int i = 0; i < M; i++) {
   
        cin >> j >> k >> A[j][k];
        A[k][j] = A[j][k];
    }

    // 最短路径算法
    int visit[N]; // 记录是否在点集中
    int D[N]; // 记录C1到点i的最短路径
    int min, v, w;

    // 初始化(直通路径初始化)
    for (int i = 0; i < N; i++) {
   
        visit[i] = 0; 
        D[i] = A[C1][i]; // 记录直通的路径长
    }

    visit[C1] = 1; // C1加入已访问节点
    D[C1] = 0; // C1到C1路径长为0
    for (int i = 1; i < N; i++) {
    // N-1轮
        min = MAX;
        v = -1;
        for (w = 0; w < N; w++) {
   
            if (!visit[w]) {
   
                if (D[w] < min) {
   
                    v = w;
                    min = D[w];
                }
            }
        }
        if (v == -1) break;
        visit[v] = 1;
        for (w = 0; w < N; w++) {
    //加入w节点,处理D[w]
            if (!visit[w] && A[v][w] != MAX) {
    // 访问未访问且有直通路径的节点w
                if (min + A[v][w] < D[w]) {
    // 如果当前记录的最短路径大于经过v的路径
                    D[w] = min + A[v][w]; // 更新D[w]
                } 
            }
        }
    }
}

应用

参考《算法笔记》与《算法笔记-上机训练实战指南》,柳婼大神的博客

PAT1003

#include <iostream>
#define MAX 9999999

using namespace std;
int main() {
   
    int N, M;
    int C1, C2;
    int V[N]; // 记录每个城市的救援队数量
    int A[N][N]; // 记录路径长度

    cin >> N >> M >> C1 >> C2;

    fill_n(&A[0][0], N * N, MAX); // MAX表示不可达

    for (int i = 0; i < N; i++) cin >> V[i];

    int j, k; // 无向邻接图对称!
    for (int i = 0; i < M; i++) {
   
        cin >> j >> k >> A[j][k];
        A[k][j] = A[j][k];
    }

    // 最短路径算法
    int visit[N]; // 记录是否在点集中
    int D[N]; // 记录C1到点i的最短路径
    int W[N]; // 记录C1到点i救援队伍数量
    int count[N]; // 记录C1到点i最短路径数
    int min, v, w;

    // 初始化(直通路径初始化)
    for (int i = 0; i < N; i++) {
   
        visit[i] = 0; 
        D[i] = A[C1][i]; // 记录直通的路径长
        if (A[C1][i] != MAX) W[i] = V[C1] + V[i]; // 记录直通连接的路径权值
        else W[i] = 0;
        count[i] = 1; // C1到i肯定有一条路径
    }

    visit[C1] = 1; // C1加入已访问节点
    D[C1] = 0; // C1到C1路径长为0
    W[C1] = V[C1];
    for (int i = 1; i < N; i++) {
   
        min = MAX;
        v = -1;
        for (w = 0; w < N; w++) {
   
            if (!visit[w]) {
   
                if (D[w] < min) {
   
                    v = w;
                    min = D[w];
                }
            }
        }
        if (v == -1) break;
        visit[v] = 1;
        for (w = 0; w < N; w++) {
    //加入w节点,处理D[w],W[w],count[w]
            if (!visit[w] && A[v][w] != MAX) {
    // 访问未访问且有直通路径的节点w
                if (min + A[v][w] < D[w]) {
    // 如果当前记录的最短路径大于经过v的路径
                    D[w] = min + A[v][w]; // 更新D[w]
                    count[w
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值