首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> C++ 入門

HDU Escape:網絡流與二進制壓縮的巧妙結合

     編輯:C++ 入門

問題背景

世界末日來臨,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),極大地壓縮圖的規模。

算法流程

  1. 讀入 n, m。初始化 ope[1< 為 0。
  2. 對每個人,讀入 m 個 0/1,構建掩碼 k,ope[k]++。
  3. 讀入每顆星星的容量 f,建立邊 (星星節點, 汇點, f)。
  4. 對每個非零 ope[k]:
    • 建立邊 (源點, 掩碼節點, ope[k])。
    • 對每個 j(0 ≤ j < m),若 k & (1<,建立邊 (掩碼節點, 星星j節點, ope[k])。
  5. 運行最大流算法(Dinic),判斷最大流是否 ≥ n。

代碼關鍵結構(Dinic 實現)

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。
  • Dinic 在此規模下極快,時間複雜度 O(E√V) 遠小於限制。

總結與啟發

本題展示了「狀態壓縮 + 網絡流」的經典組合:

  • 當左側節點屬性可由位掩碼表示且種類較少時,合併同類節點可指數級減少圖規模。
  • Dinic 算法配合當前弧優化(cur[])是解決中等規模最大流的標準選擇。
  • 讀入優化(Read() 手寫快速輸入)在大數據量下至關重要。

這一技巧在「分配任務」「資源調度」「匹配問題」等場景中廣泛適用,值得熟練掌握。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved