Dijkstra迪傑斯特拉求最短路和最短路的條數和各個點權值的最大值

小程xy發表於2024-04-24

作為一個城市的緊急救援隊隊長,你會得到一張你所在國家的特殊地圖。 該地圖顯示了由一些道路連線的幾個分散的城市。
地圖上標出了每個城市的救援隊伍數量以及任意兩個城市之間每條道路的長度。 當其他城市接到緊急電話時,你的工作就是儘快帶領你的人員趕到現場,同時在途中召集儘可能多的人手。

輸入規格:

每個輸入檔案包含一個測試用例。 對於每個測試用例,第一行包含 4 個正整數:N (≤500) - 城市數量(城市編號從 0 到 N−1),M - 道路數量,C 1 和 C 2 - 分別是您當前所在的城市和必須救援的城市。 下一行包含N個整數,其中第i個整數是第i個城市的救援隊數量。 接下來是M行,每行描述一條具有三個整數c 1 、c 2 和L的道路,這三個整數分別是由一條道路連線的一對城市和該道路的長度。 保證從C 1 到C 2 至少存在一條路徑。

輸出規格:

對於每個測試用例,在一行中列印兩個數字:C 1 和 C 2 之間不同的最短路徑的數量,以及您可能聚集的救援隊的最大數量。 一行中的所有數字必須恰好由一個空格分隔,並且行尾不允許有多餘的空格。

輸入示例:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

示例輸出:

2 4

迪傑斯特拉主要思想就是: 每次選取距離源點最近的 不在源點這個集合 的點,並把該點加入源點這個集合,然後更新一下其他點到源點的最短距離,進行 n - 1次就行了

這裡講一下 cnt 和 num 陣列
cnt 陣列儲存的是 從源點到達 點i的最短距離的總個數
num 陣列儲存的是 從源點到達 點i的最短距離前提下 所能聚集的救援隊數量的最大值

解釋一下為什麼dist[t] + g[t][j] == dist[j]時, cnt[j] += cnt[t]; 如下圖 假設源點是1,cnt[4] = 3,即有3條達到4的最短路,那麼cnt[3] = cnt[3] + cnt[4] = 4

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 510;
    int g[N][N], dist[N], Peonum[N];
    int cnt[N], num[N];     // 最短路的條數 和 最短路前提下最多能拉多少救援人員
    bool st[N];             // 標記,選過的點不再選
    int n, m, start, save;

    void djs()
    {
        memset(dist, 0x3f, sizeof dist); 

        // 初始化
        dist[start] = 0;
        cnt[start] = 1;     
        num[start] = Peonum[start];

        for (int i = 0; i < n; i ++)
        {
            int t = -1;
            for (int j = 0; j < n; j ++)
                if (!st[j] && (t == -1 || dist[j] < dist[t]))
                    t = j;
            st[t] = true;
            for (int j = 0; j < n; j ++)
            {
                if (dist[t] + g[t][j] < dist[j])
                {
                    dist[j] = dist[t] + g[t][j];
                    cnt[j] = cnt[t];
                    num[j] = num[t] + Peonum[j];
                }
                else if (dist[t] + g[t][j] == dist[j])
                {
                    cnt[j] += cnt[t];
                    num[j] = max(num[j], num[t] + Peonum[j]);
                }
            }
        }
    }
    int main()
    {
        cin >> n >> m >> start >> save;
        memset(g, 0x3f, sizeof g);          // 初始化,最開始沒有點是相連的 (0x3f是個很大的值)
        for (int i = 0; i < n; i ++) cin >> Peonum[i];
        for (int i = 0; i < m; i ++)
        {
            int a, b, c; cin >> a >> b >> c;
            g[a][b] = g[b][a] = min(g[a][b], c);
        }
        djs();
        cout << cnt[save] << ' ' << num[save] << endl;
        return 0;
    }

覺得寫的不錯的話,點個贊吧~

相關文章