Task Schedule(HDOJ 3572)
Problem Description
Our geometry princess XMM has stoped her study in computational geometry to concentrate on her newly opened factory. Her factory has introduced M new machines in order to process the coming N tasks. For the i-th task, the factory has to start processing it at or after day Si, process it for Pi days, and finish the task before or at day Ei. A machine can only work on one task at a time, and each task can be processed by at most one machine at a time. However, a task can be interrupted and processed on different machines on different days.
Now she wonders whether he has a feasible schedule to finish all the tasks in time. She turns to you for help.
Input
On the first line comes an integer T(T<=20), indicating the number of test cases.
You are given two integer N(N<=500) and M(M<=200) on the first line of each test case. Then on each of next N lines are three integers Pi, Si and Ei (1<=Pi, Si, Ei<=500), which have the meaning described in the description. It is guaranteed that in a feasible schedule every task that can be finished will be done before or at its end day.
Output
For each test case, print “Case x: ” first, where x is the case number. If there exists a feasible schedule to finish all the tasks, print “Yes”, otherwise print “No”.
Print a blank line after each test case.
Sample Input
2 4 3 1 3 5 1 1 4 2 3 7 3 5 9 2 2 2 1 3 1 2 2
Sample Output
Case 1: Yes Case 2: Yes
My Code
有n个任务和m台机器,每个任务可以在第si到第ei天内任选pi天完成。
(1)每天只能同时做m个任务,因为只有m台机器,每台机器只能同时做一个任务。
(2)每个任务同时只能有由一个机器做,所以每个任务需要做pi天
首先建立一个超级源点,然后和每个任务连起来,容量为pi,如果这n个弧都满流就说明,所有任务都完成了。
每个任务和si到ei的每一天连起来,容量为1,因为第(2)条
最后每一天都和超级汇点连起来,容量为m,因为第(1)条
剩下的就跑最大流了,如果最大流等于∑pi,就说明任务完成了
#include
#include
#include
#define maxn 1005
#define maxm 250005
#define inf 0x3f3f3f3f
using namespace std;
int T;
int n, m;
struct edge
{
int v;
int c;
int next;
} e[maxm << 1];
int tot;
int cnt;
int head[maxn];
int cur[maxn];
void add(int u, int v, int c)
{
e[++tot].v = v;
e[tot].c = c;
e[tot].next = head[u];
head[u] = tot;
}
int dep[maxn];
bool bfs(int s, int t)
{
queue q;
memset(dep, 0, sizeof(dep));
dep[s] = 1;
q.push(s);
for (int i = 0; i <= t; i++) //总的点数不是n,而是t+1
cur[i] = head[i];
while (!q.empty())
{
s = q.front();
q.pop();
for (int i = head[s]; ~i; i = e[i].next)
if (e[i].c && !dep[e[i].v])
{
dep[e[i].v] = dep[s] + 1;
if (e[i].v == t)
return true;
q.push(e[i].v);
}
}
return false;
}
int dfs(int s, int t, int flow)
{
if (s == t || !flow)
return flow;
int ans = 0;
for (int &i = cur[s]; ~i; i = e[i].next)
if (e[i].c && dep[e[i].v] == dep[s] + 1)
{
int res = dfs(e[i].v, t, min(flow, e[i].c));
if (!res)
dep[e[i].v] = 0;
e[i].c -= res;
e[i ^ 1].c += res;
ans += res;
flow -= res;
if (!flow)
break;
}
return ans;
}
void init()
{
memset(e, -1, sizeof(e));
memset(head, -1, sizeof(head));
tot = -1;
}
int dinic(int s, int t)
{
int ans = 0;
while (bfs(s, t))
ans += dfs(s, t, inf);
return ans;
}
int main()
{
cin >> T;
while (T--)
{
init();
cin >> n >> m;
int sum = 0;
int maxd = 0;
int s = 0;
for (int i = 1; i <= n; i++)
{
int pi, si, ei;
cin >> pi >> si >> ei;
sum += pi; //记录源点流出的最大流量,即每个任务完成所需时间的累加
maxd = max(ei, maxd); //记录最晚的那一天
add(s, i, pi); //超级源点到每个任务的流量为任务所需时间pi
add(i, s, 0); //反悔边
for (int j = si; j <= ei; j++)
{
add(i, j + n, 1); //每个任务和其开始到结束的每一天连起来,容量为1
add(j + n, i, 0); //因为做一天只能算一天的任务,不能一天把pi天的都做完
}
}
int t = maxd + n + 1; //超级汇点
for (int i = n + 1; i < t; i++)
{
add(i, t, m); //每一天到汇点的容量为m
add(t, i, 0); //因为每天只能同时有m个机器工作
}
if (dinic(s, t) == sum) //如果每个任务都干满了pi天,那就说明完成了
cout << "Case " << ++cnt << ": Yes" << endl;
else
cout << "Case " << ++cnt << ": No" << endl;
if (t)
cout << endl;
}
return 0;
}