N 個島嶼(0~N-1),橋分為普通橋(無限通行)和危橋(最多通行 2 次)。Alice 需在 a1、a2 間往返 an 次,Bob 需在 b1、b2 間往返 bn 次。判斷是否存在滿足所有約束的路徑方案。N < 50,an, bn ≤ 50。
上述模型可能出現「Alice 的流跑到了 Bob 的匯點」導致假陽性。解決方案:交換 Bob 的源匯點重跑一次(即 b1↔b2 互換),若兩次均滿流則真正可行。原理:若存在錯配流,交換後必會導致瓶頸使流量不足。
// 邊結構
struct Edge { int to, cap, rev; };
vector G[MAXN];
int level[MAXN], iter[MAXN];
void add_edge(int from, int to, int cap) {
G[from].push_back({to, cap, (int)G[to].size()});
G[to].push_back({from, 0, (int)G[from].size()-1});
}
bool bfs(int s, int t) {
memset(level, -1, sizeof(level));
queue q; level[s] = 0; q.push(s);
while (!q.empty()) {
int v = q.front(); q.pop();
for (auto &e : G[v])
if (e.cap > 0 && level[e.to] < 0)
level[e.to] = level[v] + 1, q.push(e.to);
}
return level[t] >= 0;
}
int dfs(int v, int t, int f) {
if (v == t) return f;
for (int &i = iter[v]; i < G[v].size(); i++) {
Edge &e = G[v][i];
if (e.cap > 0 && level[v] < level[e.to]) {
int d = dfs(e.to, t, min(f, e.cap));
if (d > 0) { e.cap -= d; G[e.to][e.rev].cap += d; return d; }
}
}
return 0;
}
int max_flow(int s, int t) {
int flow = 0, inf = 1e9;
while (bfs(s, t)) {
memset(iter, 0, sizeof(iter));
int f;
while ((f = dfs(s, t, inf)) > 0) flow += f;
}
return flow;
}
// 主邏輯
bool solve() {
build_graph(); // 正常連接
if (max_flow(S, T) != total_need) return false;
swap(b1, b2); // 交換 Bob 源匯
clear_graph();
build_graph();
return max_flow(S, T) == total_need;
}
本題是「多源多匯最大流可行性判定」的經典變體。核心難點在於識別雙源雙匯不能獨立建模,必須聯合建圖並通過源匯交換驗證流向正確性。Dinic 算法模板熟練度直接決定編碼速度。