1. 程式人生 > 其它 >【LeetCode-847】訪問所有節點的最短路徑

【LeetCode-847】訪問所有節點的最短路徑

問題

存在一個由 n 個節點組成的無向連通圖,圖中的節點按從 0 到 n - 1 編號。

給你一個數組 graph 表示這個圖。其中,graph[i] 是一個列表,由所有與節點 i 直接相連的節點組成。

返回能夠訪問所有節點的最短路徑的長度。你可以在任一節點開始和停止,也可以多次重訪節點,並且可以重用邊。

提示:

  • n == graph.length
  • 1 <= n <= 12
  • 0 <= graph[i].length <n
  • graph[i] 不包含 i
  • 如果 graph[a] 包含 b ,那麼 graph[b] 也包含 a
  • 輸入的圖總是連通圖

示例

輸入: graph = [[1],[0,2,4],[1,3,4],[2],[1,2]]
輸出:

4
解釋: 一種可能的路徑為 [0,1,4,2,3]

解答

class Solution {
public:
    int shortestPathLength(vector<vector<int>>& graph) {
        int n = graph.size();
        queue<tuple<int, int, int>> q; // idx, state, dist
        vector<vector<bool>> vis(n, vector<bool>(1 << n));
        for (int i = 0; i < n; i++) {
            q.emplace(i, 1 << i, 0);
            vis[i][1 << i] = true;
        }
        while (!q.empty()) {
            auto [idx, state, dist] = q.front();
            q.pop();
            if (state == (1 << n) - 1) return dist;
            for (int v : graph[idx]) {
                int cur_state = state | (1 << v);
                if (vis[v][cur_state]) continue;
                q.emplace(v, cur_state, dist + 1);
                vis[v][cur_state] = true;
            }
        }
        return 0;
    }
};

重點思路

本題知識點:

  • 多源BFS:由於每條邊等權,先處理哪個點都一樣,所以可以使用多源BFS;
  • 狀態壓縮:可以使用0和1表示是否經過某一個節點,本題規定最多12個節點,所以可以使用一個int型別的整數,取低12位表示遍歷狀態。

假設有8個節點,當表示狀態的整數為\((...0011111111)_2\)時,表示此時已經遍歷了所有節點,多源BFS保證當前一定是遍歷完成的最短距離,直接輸出當前距離即可。為保證每個“狀態”(兩個約束,當前節點的idx與對應的遍歷狀態state)只經過一次,使用二維陣列儲存已遍歷狀態。有點類似遍歷二維陣列時儲存的橫縱座標,本質是一樣的,保證不會經過重複“狀態”。