小時候玩過「一筆畫」嗎?筆不離紙、每條線只能描一次,把整個圖形畫完——這就是歐拉路徑(Euler Path)要解的事: 一趟走遍所有邊、不重複。另一個看似八竿子打不著的難題是2-SAT:一堆事情每件都只能二選一(要 A 或要 B), 選項之間又互相牽制(選了這個就不能選那個),問到底喬不喬得出一組彼此不打架的安排。 神奇的是,這兩題最後都能「畫成一張圖」再交給電腦去走。下面你會看到它們各自怎麼在圖上一步步逼出答案。
兩個乍看無關、實際都靠圖結構解決的經典問題:歐拉路徑(Euler Path,Hierholzer 演算法)要找一條「一筆畫」路徑, 每條邊恰走一次,用顯式棧邊走邊刪邊、走到死路就彈棧回填路徑; 2-SAT則是把布林變數的二元子句可滿足性問題「翻譯」成有向圖上的蘊含邊, 再靠 Tarjan 強連通分量一次性判定矛盾並決定每個變數的賦值。一個是「圖論問題直接在圖上求解」, 一個是「把邏輯問題轉成圖論問題再求解」。
先計算各頂點度數:奇度頂點數須為 0(歐拉迴路)或 2(歐拉路徑)且圖連通,否則無解。 決定起點後入棧;每次看棧頂節點 v,若還有剩餘邊就取 id 最小的鄰居 u、刪除邊 v-u(雙向)、u 入棧; 若 v 已無剩餘邊,就彈棧並把 v 加入路徑。棧清空後反轉路徑,即為歐拉路徑(或迴路)。
每個變數 x 拆成兩個 literal 節點 x 與 ¬x;每條子句 (a∨b) 等價於「¬a⟹b」與「¬b⟹a」兩條蘊含邊, 建成蘊含圖後跑一次 Tarjan SCC(同 dfn/low + 顯式棧,依 id 升序拜訪鄰居)。 若某個變數的 x 與 ¬x 落在同一組 SCC 即矛盾、判定無解;否則逐變數依 sccId[x] 與 sccId[¬x] 的大小決定賦值(sccId 值愈小代表在 SCC 縮點後的拓撲序中愈晚,即 sccId 較小者為真)。