給定有向無環圖(DAG),求從 s 到 t 的所有路徑必經的頂點(割點)。n ≤ 100000, m ≤ 300000。利用拓撲序性質:先求最短路(BFS/SPFA),最短路上的點按距離遞增排列。從 s 沿最短路 DFS 尋找最遠的「必經點」,迭代直到達到 t。
dist[v] 並記錄父節點 fa[v]。若 t 不可達,所有點都是割點(輸出 n)。fa 到 s,標記最短路上的點 mark[v]=1。cur = s,答案 ans=1(含 s)。cur DFS,只走 mark=1 的點,找到距離 dist 最大的點 next。next 即為下一個割點,ans++,cur = next。cur == t。在 DAG 中,s 到 t 的所有路徑長度 ≥ dist[t]。最短路上的點按 dist 嚴格遞增。若某點 v 在最短路上,且從 s 到 v 的所有路徑必經 u,則 u 是割點。DFS 找最遠可達最短路點,保證找到的點是「瓶頸」。
關鍵細節
N*3 防止越界。mark=1 的點,非最短路點直接遞歸探索,不影響割點判定。dist 比較確保找到最遠點。HDU 3313 巧妙利用 DAG 最短路的拓撲有序性,將割點查找轉化為最短路上的「瓶頸點」迭代搜索。避免了一般圖割點的 Tarjan 算法(O(n+m) 但常數大、難寫),代碼簡潔高效,是 DAG 割點問題的最佳解法。