PAT甲級 Dijkstra 相關題_C++題解

Dijkstra

PAT (Advanced Level) Practice Dijkstra 相關題ios

目錄

  • 《算法筆記》重點摘要
  • 1003 Emergency (25)

《算法筆記》 10.4.1 Dijkstra 重點摘要

對任意給出的圖 G(V,E) 和 起點 S,終點 T,求 S 到 T 的最短路徑算法

1. 簡介

  • 解決單源最短路問題
  • 只能處理全部邊權均非負的狀況數組

    若出現負數,最好使用 SPFA 算法spa

2. 鄰接矩陣

const int MAXV = 1000;
const int INF = 0x3fffffff;
int n, G[MAXV][MAXV], d[MAXV], pre[MAXV];
bool vis[MAXV] = {false};
void Dijkstra(int s){
    fill(d, d + MAXV, INF);
    d[s] = 0;
    for (int i = 0; i < n; i++) pre[i] = i;
    for (int i = 0; i < n; i++){
        int u = -1, MIN = INF;
        for (int j = 0; j < n; j++){    // 找未訪問結點中 d[] 最小的
            if (!vis[j] && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        if (u == -1) return;    // 找不到 d[u] < INF 點,說明剩下的點與起點 s 不連通
        vis[u] = true;
        for (int v = 0; v < n; v++){
            if (!vis[v] && G[u][v] != INF && d[u] + G[u][v] < d[v]){
                d[v] = d[u] + G[u][v];
                pre[v] = u;
            }
        }
    }
}
void DFS(int s, intv){
    if (v == s){
        printf("%d", s);
        return;
    }
    DFS(s,pre[v]);
    printf(" %d", v);
}

3. 第二標尺

第一標尺爲距離指針

(1) 新增邊權

如邊的花費code

int cost[MAXV][MAXV], c[MAXV];
fill(c, c + MAXV, INF);
c[s] = 0;
for (int v = 0; v < n; v++){
    if (!vis[v] && G[u][v] != INF){
        if (d[u] + G[u][v] == d[v] && c[u] + cost[u][v] < c[v]){
            pre[v] = u;
            c[v] = c[u] + cost[u][v];
        }
        else if (d[u] + G[u][v] < d[v]){
            pre[v] = u;
            d[v] = d[u] + G[u][v];
            c[v] = c[u] + cost[u][v];
        }
    }
}
(2) 新增點權

如點的權重io

int weight[MAXV], w[MAXV] = {0};
w[s] = weight[s];
for (int v = 0; v < n; v++){
    if (!vis[v] && G[u][v] != INF){
        if (d[u] + G[u][v] == d[v] && w[u] + weight[v] > w[v]){
            pre[v] = u;
            w[v] = w[u] + weight[v];
        }
        else if (d[u] + G[u][v] < d[v]){
            pre[v] = u;
            d[v] = d[u] + G[u][v];
            w[v] = w[u] + weight[v];
        }
    }
}
(3) 求最短路徑條數
int num[MAXV] = {0};
num[s] = 1;
for (int v = 0; v < n; v++){
    if (!vis[v] && G[u][v] != INF){
        if (d[u] + G[u][v] == d[v]{
            pre[v] = u;
            num[v] += num[u];
        }
        else if (d[u] + G[u][v] < d[v]){
            pre[v] = u;
            d[v] = d[u] + G[u][v];
            num[v] = num[u];
        }
    }
}

1003 Emergency (25)

題目思路

  • 兩個標尺:距離,點權;且要求最短路徑數
#include<iostream>
using namespace std;
const int MAXN = 500, INF = 0x3fffffff;
int n, s, t, G[MAXN][MAXN], weight[MAXN], d[MAXN], pathnum[MAXN], w[MAXN] = {0};
bool vis[MAXN] = {false};
void Dijkstra(){
    fill(d, d + MAXN, INF);
    d[s] = 0;
    pathnum[s] = 1;
    w[s] = weight[s];
    for (int i = 0; i < n; i++){
        int u = -1, MIN = INF;
        for (int j = 0; j < n; j++){
            if (!vis[j] && d[j] < MIN){
                u = j;
                MIN = d[j];
            }
        }
        vis[u] = true;
        for (int v = 0; v < n; v++){
            if (!vis[v] && G[u][v] != INF){
                if (d[v] == d[u] + G[u][v]){
                    pathnum[v] += pathnum[u];
                    if (w[v] < w[u] + weight[v]) w[v] = w[u] + weight[v];
                }
                else if (d[v] > d[u] + G[u][v]){
                    d[v] = d[u] + G[u][v];
                    w[v] = w[u] + weight[v];
                    pathnum[v] = pathnum[u];
                }
            }
        }
    }
}
int main()
{
    int m, u, v, len;
    scanf("%d%d%d%d", &n, &m, &s, &t);
    for (int i = 0; i < n; i++) scanf("%d", &weight[i]);
    fill(G[0], G[0] + MAXN * MAXN, INF);
    for (int i = 0; i < m; i++){
        scanf("%d%d%d", &u, &v, &len);
        G[u][v] = len;
        G[v][u] = len;
    }
    Dijkstra();
    printf("%d %d", pathnum[t], w[t]);
    return 0;
}
  • fill(G[0], G[0] + MAXN * MAXN, INF) 注意二維數組要取首地址做爲指針類型不能直接用數組名,由於它至關因而一維數組的指針,而參數要求是指針
相關文章
相關標籤/搜索