N 個任務,每個任務 i 需在 [S_i, E_i] 區間內佔用 P_i 天處理時間。M 台機器,每台每天只能處理一個任務。任務可中斷、可在不同機器、不同天處理。問是否存在可行調度。
最大流 = Σ P_i ⇔ 可行調度存在。
struct Edge { int to, cap, rev; };
vector G[MAXV];
int level[MAXV], iter[MAXV];
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) {
memset(level, -1, sizeof(level));
queue q; q.push(s); level[s]=0;
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 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 (true) {
bfs(s);
if (level[t] < 0) return flow;
memset(iter, 0, sizeof(iter));
int f;
while ((f=dfs(s,t,inf)) > 0) flow += f;
}
}
int main() {
int T; scanf("%d", &T);
for (int cs=1; cs<=T; cs++) {
int N, M; scanf("%d%d", &N, &M);
vector P(N+1), S(N+1), E(N+1);
int Tmax = 0, sumP = 0;
for (int i=1; i<=N; i++) {
scanf("%d%d%d", &P[i], &S[i], &E[i]);
Tmax = max(Tmax, E[i]);
sumP += P[i];
}
// 初始化圖
int S_node = 0, T_node = Tmax + N + 1;
for (int i=0; i<=T_node; i++) G[i].clear();
// S -> 天
for (int d=1; d<=Tmax; d++) add_edge(S_node, d, M);
// 天 -> 任務
for (int i=1; i<=N; i++) {
int task_node = Tmax + i;
for (int d=S[i]; d<=E[i]; d++)
add_edge(d, task_node, 1);
// 任務 -> T
add_edge(task_node, T_node, P[i]);
}
int flow = max_flow(S_node, T_node);
printf("Case %d: %s\n\n", cs, flow == sumP ? "Yes" : "No");
}
}
Case x: Yes/No 後空行。此題是「區間調度 + 資源限制」建模為最大流的經典案例,展示了流網絡處理時間資源分配的強大表達力。