圖的搜尋與分解

把圖的探索當作設計工具(graph exploration as a design tool)

許多看起來不像圖的問題,一旦你把它畫成圖並有系統地走過它,就變得容易了。你能從這座機場到那座機場嗎?這個迷宮有解嗎?爬蟲從首頁能抵達哪些網頁?每一個其實都是關於圖的問題,而答案會從一趟有紀律、恰好碰到每個可達部分一次的走訪中浮現。「把圖的探索當作設計工具」的想法就是:這一趟走訪——以廣度優先或深度優先搜尋進行——是一具可重複使用的引擎,你把小任務拴在它上面。

共用的骨架很簡單:維護一個已拜訪頂點的集合,從某個起點出發,反覆取出一個尚未探索的頂點、標記為已拜訪、再把它尚未拜訪的鄰居排入待處理。BFS 用佇列來做,因此像漣漪般依距離遞增一圈圈擴散;DFS 用堆疊(或遞迴)來做,因此沿一條路徑盡可能往下衝、走不下去才退回。由於兩者各把每個頂點標記一次、各檢視每條邊一次,配上鄰接串列都跑在 O(n + m)。它的威力在於你不改動走訪本身——只是在恰當時機掛上一個小動作:數要走幾趟才能覆蓋一切(連通分量)、記下每個頂點離起點的距離(以邊數計的最短路徑)、把頂點交替著色以測試兩側性(二分圖)、記下頂點完成的順序(拓樸排序)、或留意是否有一條回到祖先的邊(環偵測)。

這正是圖搜尋被視為一種設計範式、而不只是兩個程序的原因。一旦你能把問題看成「從這裡抵達一切,並在過程中觀察某件事」,你就免費繼承了一個正確、線性時間的走訪,只需設計那個小小的觀察。誠實的界限:探索能回答可達性與結構(誰連到誰、隔幾跳、依什麼順序),但純 BFS 與 DFS 忽略邊的權重——若要在不同成本下找最便宜的路徑,你需要戴克斯特拉或貝爾曼-福特的加權機制;若要回答容量問題,你需要網路流。清楚哪些問題裸走訪能答、哪些不能,是用好它的一半功夫。

迷宮就是一張圖:格子是頂點,相通的通道是邊。從入口跑 BFS,一旦彈出出口就停下——BFS 的同心圈不只告訴你「有解嗎?」,還給出步數最少的路徑。換成 DFS,你得到的是一條深入遊走的完整路徑;換成數分量,你便知道有幾個彼此不通的房間。

一趟走訪、多種答案:你重複使用同一趟走訪,只更換沿途記錄的那件小事。

裸走訪回答的是可達性與跳數,而非最低成本。一旦邊帶有不同權重,BFS 的「最少邊數」就不再等於「最便宜」,你必須改用加權最短路徑演算法。

又称
traversal-based design以走訪為基礎的設計