有向圖,每條邊每天通行上限 c,每人每天只能走一條邊。T 人從 1 號點出發,求最少天數到達 N 號點。
第 d 天的節點 v 編號為 d×N + v。
邊:d×N + u → (d+1)×N + v,容量 = 原邊容量。
每天原地停留:d×N + v → (d+1)×N + v,容量 = INF。
超級源 S → 0×N + 1 容量 = T。
每天終點 d×N + N → 超級匯 T 容量 = INF。
從第 1 天開始,每增加一天就添加一層節點與邊,在現有流網絡上增量跑最大流。當累積流量達到 T 時,當前天數即為答案。
上界:最長路徑 ≤ N,T 人排隊 ≤ T+N 天。
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 5010;
const int INF = 0x3f3f3f3f;
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});
}
void bfs(int s) {
fill(level, level + MAXN, -1);
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);
}
}
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, f;
while (true) {
bfs(s); if (level[t] < 0) return flow;
fill(iter, iter + MAXN, 0);
while ((f = dfs(s, t, INF)) > 0) flow += f;
}
}
struct OrigEdge { int u, v, c; } edges[5010];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, T; cin >> n >> m >> T;
for (int i = 0; i < m; i++) cin >> edges[i].u >> edges[i].v >> edges[i].c;
int S = 0, T_node = MAXN - 1;
add_edge(S, 1, T); // 第 0 天第 1 點
for (int day = 1; day <= n + T; day++) {
// 原圖邊:day-1 層 → day 層
for (int i = 0; i < m; i++) {
int u = edges[i].u, v = edges[i].v, c = edges[i].c;
int from = (day-1)*n + u;
int to = day*n + v;
add_edge(from, to, c);
}
// 停留邊
for (int v = 1; v <= n; v++) {
int from = (day-1)*n + v;
int to = day*n + v;
add_edge(from, to, INF);
}
// 終點連超級匯
add_edge(day*n + n, T_node, INF);
// 增量最大流(實際需在 max_flow 內部支持增量,這裡簡化重跑)
// 完整版需維護殘留網絡增量跑流
int flow = max_flow(S, T_node);
if (flow >= T) { cout << day << '\n'; return 0; }
}
return 0;
}
day×N + v 統一映射