Task Schedule
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 11276 Accepted Submission(s): 3423
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.
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.
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.
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
一、原题地址
二、大致题意
现在有n项任务,将分配给m个机器去做。每个任务有他的持续时间Pi, 开始时间Si(或者在这个时间之后开始任务),结束时间Ei(或者在这个时间之前结束任务)。每项任务可以零零碎碎的分配给每台机器,即它能被分成好几段来完成。但是每台机器一天是只能去接受一项任务的。
三、大致思路
我们将每一项任务看作一个点,因为任务完成的天数最多是500天,所以我们可以把每一天也看作是一个个点。
建立一个超级源点,将它与所有的任务点相连,那么这里每条边的容量也就自然是这个任务点所需被工作的时间Pi。
每个任务点应该与他对应的可以被工作的天数点相连,容量为1
最后再将所有天数点连接超级汇点,因为有m台机器,也就是说每天最多只能完成m段任务,那么这些边的容量就是m了。
完成了建图以后,套入Dinic。只需要判断汇点的最大流量是否等于所有任务需求的总量就可以了。
四、代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<vector>
#include<queue>
#include<set>
#include<map>
#include<stack>
using namespace std;
const int inf = 0x3f3f3f3f;
#define LL long long int
long long gcd(long long a, long long b) { return a == 0 ? b : gcd(b % a, a); }
int T;
int n, m;
int sum;
const int maxn = 1005;
struct Edge
{
Edge() {}
Edge(int from, int to, int cap, int flow) :from(from), to(to), cap(cap), flow(flow) {}
int from, to, cap, flow;
};
struct Dinic
{
int n, m, s, t; //结点数,边数(包括反向弧),源点与汇点编号
vector<Edge> edges; //边表 edges[e]和edges[e^1]互为反向弧
vector<int> G[maxn]; //邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn]; //BFS使用,标记一个节点是否被遍历过
int d[maxn]; //从起点到i点的距离
int cur[maxn]; //当前弧下标
void init(int n, int s, int t)
{
this->n = n, this->s = s, this->t = t;
for (int i = 1; i <= n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from, int to, int cap)
{
edges.push_back(Edge(from, to, cap, 0));
edges.push_back(Edge(to, from, 0, 0));
m = edges.size();
G[from].push_back(m - 2);
G[to].push_back(m - 1);
}
bool BFS()
{
memset(vis, 0, sizeof(vis));
queue<int> Q;//用来保存节点编号的
Q.push(s);
d[s] = 0;
vis[s] = true;
while (!Q.empty())
{
int x = Q.front(); Q.pop();
for (int i = 0; i<G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (!vis[e.to] && e.cap>e.flow)
{
vis[e.to] = true;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a)
{
if (x == t || a == 0)return a;
int flow = 0, f;//flow用来记录从x到t的最小残量
for (int& i = cur[x]; i<G[x].size(); i++)
{
Edge& e = edges[G[x][i]];
if (d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap - e.flow)))>0)
{
e.flow += f;
edges[G[x][i] ^ 1].flow -= f;
flow += f;
a -= f;
if (a == 0) break;
}
}
return flow;
}
int Maxflow()
{
int flow = 0;
while (BFS())
{
memset(cur, 0, sizeof(cur));
flow += DFS(s, inf);
}
return flow;
}
};
void solve()
{
scanf("%d %d", &n, &m);
Dinic DC;
int sum = 0;
DC.init(500 + n + 2, 0, 500 + 1 + n);
for (int i = 1; i <= n; i++)
{
int w, u, v;
scanf("%d %d %d", &w, &u, &v);
sum += w;
DC.AddEdge(0, i, w);
for (int j = n + u; j <= n + v; j++)
{
DC.AddEdge(i, j, 1);
}
}
for (int i = n + 1; i <= n + 500; i++)
{
DC.AddEdge(i, 500 + n + 1, m);
}
int ans = DC.Maxflow();
if (sum == ans)printf("Yes\n");
else printf("No\n");
}
int main()
{
int Kase = 1;
scanf("%d", &T);
while (T--)
{
printf("Case %d: ", Kase++);
solve();
printf("\n");
}
getchar();
getchar();
}