世界末日來臨,n 個地球人想逃往星星生活。每顆星星容納人數有限,且每個人只能去特定的星星(由二進制掩碼表示)。判斷是否所有人都能成功逃離。
本質上是一個二分圖完美匹配問題:左側 n 個人,右側 m 顆星星(每顆有容量上限)。人 i 能去星星 j,當且僅當其掩碼第 j 位為 1。求是否存在流量為 n 的可行流。
直接建圖:n 個人,每人連接最多 m 顆星星,邊數 O(n·m)。若 n 很大(如 10⁴),邊數達 10⁵ 以上,常規 Dinic 可能超時或記憶體不足。
關鍵觀察:許多人擁有相同的星星偏好掩碼。將擁有相同掩碼 k 的人合併為一個「超級節點」,容量為該掩碼出現的次數 ope[k]。掩碼總數最多 2^m(m ≤ 10 時僅 1024),極大地壓縮圖的規模。
ope[1< 為 0。 ope[k]++。(星星節點, 汇點, f)。ope[k]:
(源點, 掩碼節點, ope[k])。k & (1<,建立邊 (掩碼節點, 星星j節點, ope[k])。 struct Edge { int from, to, cap, flow; };
class MF {
vector edges;
vector G[MAXN];
int n, s, t, d[MAXN], cur[MAXN];
bool vst[MAXN];
// BFS 構建層次圖
bool BFS() { ... }
// DFS 尋找增廣路
int DFS(int u, int a) { ... }
// 最大流主循環
int Maxflow() { ... }
// 讀入並構建壓縮圖
bool Solve(int n, int m) { ... }
};
1 (源) + 2^m (掩碼) + m (星星) + 1 (匯) ≤ 1126(m≤10)。O(2^m · m) ≤ 10240。本題展示了「狀態壓縮 + 網絡流」的經典組合:
cur[])是解決中等規模最大流的標準選擇。Read() 手寫快速輸入)在大數據量下至關重要。這一技巧在「分配任務」「資源調度」「匹配問題」等場景中廣泛適用,值得熟練掌握。