【LeetCode-847】訪問所有節點的最短路徑
阿新 • • 發佈:2021-08-07
問題
存在一個由 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
)只經過一次,使用二維陣列儲存已遍歷狀態。有點類似遍歷二維陣列時儲存的橫縱座標,本質是一樣的,保證不會經過重複“狀態”。