這是一道經典的二分圖最大費用最大流問題,核心難點在於處理「至少選取」的下界約束。
給定 N × M 矩陣,每個格子有一個非負整數權值。第 i 行至少要選 Ki 個數,第 j 列至少要選 Kj 個數。求滿足條件下被選數字之和的最小值。
直接處理「至少選」的下界約束很麻煩,但可以巧妙轉化:
最小和 = 所有元素總和 - 最大可不選元素之和
具體轉化:
bool BellmanFord(int s, int t, LL &ans) {
for (int i = 0; i <= t; i++) d[i] = -INF; // 初始化為 -INF(求最大)
memset(inq, 0, sizeof(inq));
d[s] = 0; inq[s] = 1; p[s] = 0; a[s] = INF;
queue<int> Q; Q.push(s);
while (!Q.empty()) {
int u = Q.front(); Q.pop(); inq[u] = 0;
for (int i = 0; i < G[u].size(); i++) {
Edge &e = edges[G[u][i]];
if (e.cap > e.flow && d[e.to] < d[u] + e.cost) { // 放寬條件:求最大
d[e.to] = d[u] + e.cost;
p[e.to] = G[u][i];
a[e.to] = min(a[u], e.cap - e.flow);
if (!inq[e.to]) { Q.push(e.to); inq[e.to] = 1; }
}
}
}
if (d[t] < 0) return false; // 無增廣路或最大費用為負
ans += (LL)d[t] * (LL)a[t];
// 更新流量...
return true;
}
| 層面 | 最小費用流 | 最大費用流 |
|---|---|---|
| 距離初始化 | +INF | -INF |
| 鬆弛條件 | d[v] > d[u] + cost | d[v] < d[u] + cost |
| 終止條件 | d[t] == INF | d[t] < 0 |
官方題解使用鄰接表 + 手寫 SPFA,邏輯相同但代碼風格不同。兩份代碼核心思想一致:將有下界的費用流轉化為只有上界的普通費用流,這是解決此類問題的通用技巧。