最短路專題1 | CodeForces 601A - 混合Dijkstra算法

最短路專題1 | CodeForces 601A - 混合Dijkstra算法

前言

這個十一沒有出去玩,花了一些時間在寫之前提過的markdown編輯器,本文就是用這個編輯器寫的2333,今天準備寫咱們的新專題 — 最短路。另外之前提過專題的題目主要使用kuangbin系列,現在改變主意了,專題題目全部使用CodeForces上的題目,原因主要是POJ等國內的OJ系統不能看源代碼,而且題目質量稍微欠缺一些,然後沒有區分度。

CodeForces能夠看到高手寫的代碼,題目質量相對好些,然後每個題目的難易都用a/b/c/d標明瞭。
OK,開始看題。

601A. The Two Routes

In Absurdistan, there are n towns (numbered 1 through n) and m bidirectional railways. There is also an absurdly simple road network — for each pair of different towns x and y, there is a bidirectional road between towns x and y if and only if there is no railway between them. Travelling to a different town using one railway or one road always takes exactly one hour.
有n個城市,m個雙向鐵軌。還有一個公路網絡,對於每一對城鎮x和y,如果它們沒有鐵路,那麼就一定會有公路。去一個不同的城鎮,不管是鐵路還是公路,都需要一個小時。

A train and a bus leave town 1 at the same time. They both have the same destination, town n, and don’t make any stops on the way (but they can wait in town n). The train can move only along railways and the bus can move only along roads.
火車和汽車從1號站同時離開,同時開往n。

You’ve been asked to plan out routes for the vehicles; each route can use any road/railway multiple times. One of the most important aspects to consider is safety — in order to avoid accidents at railway crossings, the train and the bus must not arrive at the same town (except town n) simultaneously.
你需要計劃一下出行的方案,每一條線路都能夠使用公路或者鐵路。爲了避免意外發生,火車和汽車不能夠同時到達同一個城鎮(n除外)。

Under these constraints, what is the minimum number of hours needed for both vehicles to reach town n (the maximum of arrival times of the bus and the train)? Note, that bus and train are not required to arrive to the town n at the same moment of time, but are allowed to do so.

Input

The first line of the input contains two integers n and m (2 ≤ n ≤ 400, 0 ≤ m ≤ n(n - 1) / 2) — the number of towns and the number of railways respectively.
第一行包含2個整數n和m,n是城市的數量,m是鐵路的數量。

Each of the next m lines contains two integers u and v, denoting a railway between towns u and v (1 ≤ u, v ≤ n, u ≠ v).
下面的m行表示路線

You may assume that there is at most one railway connecting any two towns.

Output

Output one integer — the smallest possible time of the later vehicle’s arrival in town n. If it’s impossible for at least one of the vehicles to reach town n, output  - 1.
輸出最短路徑

Examples

input
4 2
1 3
3 4

output
2

Note
In the first sample, the train can take the route 1341\to3\to4 and the bus can take the route1241\to2\to4 . Note that they can arrive at town 4 at the same time.

In the second sample, Absurdistan is ruled by railwaymen. There are no roads, so there’s no way for the bus to reach town 4.

一道最簡單的最短路徑問題,權重可以看作1。

題目大意是有鐵路和公路兩種路,而且兩種方式走的交通工具不能在中途相遇。

此外,有鐵路的地方肯定沒有公路。

這種情況下就會有一個結論,就是至少有一種交通可以直接1到n

這樣只需要對另一種跑一個最短路就OK了。

#include <algorithm>
#include <queue>
#include <string.h>

// 圖
int g[410][410];

//0號節點到節點i的路徑長度
int d[410];

int main() {
#ifdef __MSYS__
    freopen("test.txt", "r", stdin);
#endif

    // 輸入部分
    int n, m;
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        g[a][b] = g[b][a] = 1;
    }

    std::queue<int> q;
    //放入0號節點
    q.push(0);
    memset(d, -1, sizeof(d));
    d[0] = 0;
    
    while (!q.empty()) {
        int v = q.front();
        q.pop();
        // 最後一個節點
        if (v == n - 1) {
            printf("%d\n", d[v]);
            return 0;
        }
        // 遍歷所有相鄰的節點
        for (int i = 0; i < n; i++)
            //g[v][i]爲0,g[0][n-1]爲1,如果火車直連,那麼g[v][i]不能有火車,也就是0,計算的是汽車的最短路徑
            //g[v][i]爲1,g[0][n-1]爲0,如果火車不直連,那麼汽車必然是直連的,計算的是火車的最短路徑
            if (g[v][i] ^ g[0][n - 1]) {
                if (d[i] == -1) {
                    q.push(i);
                    d[i] = d[v] + 1;
                }
            }
    }
    printf("-1\n");
    return 0;
}

這裏使用的是Dijkstra(注意後面沒有字母l)算法,這裏我們簡單回顧一下dij算法。

首先,對於一個網絡G,我們選取一個點A作爲起始點,放入隊列Q。

然後,我們開始處理隊列Q,如果Q存在元素,就一直執行。

每次執行,都是從隊列中取得d值最小的元素v,然後遍歷這個v相鄰的節點i,如果d[i]爲INF,也就是離節點A的距離爲無窮大,那麼就將這個元素加入到Q中,更新d[i]=min{d[i], d[i]+w[v][i]}。

對於dij算法來說,可以將圖分爲2部分,一部分是dij的最短路圖G1,另外剩下的是還沒有加入的圖G2。每次循環都會在G2中尋找節點i,這個節點i必須是G2中d值最小的,然後更新節點i相鄰的節點的d值。整個過程是G2的節點流向G1,最終G1就是一個最短路徑圖。

個人公衆號(acm-clan):ACM算法日常

專注於基礎算法的研究工作,深入解析ACM算法題,五分鐘閱讀,輕鬆理解每一行源代碼。內容涉及算法、C/C++、機器學習等。

發佈了24 篇原創文章 · 獲贊 141 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章