题意:
有 N(N<=500)个任务..有M(<=200)个机器。第i个任务要在大于等于第Si天开始做,小于等于Ei天完成。.第i个任务要做Pi天。每个任务不一定要连续的做,即在[Si,Ei]间做满Pi天即可。每个机器每天只能完成一个任务一天的工作量。每个任务每次只能被一台机器做。问每个任务是否都能按时完成。
做法:
建图如下:设超级源点1,到每个任务点之间的容量为Pi,每个任务点到第Si至Ei天都建一条边,容量为1。每一天到超级汇点建边,容量为m。跑一遍最大流,如果超级源点与超级汇点之间的最大流等于P之和,则可以按时完成任务。(可以这么理解:把每个任务分配到每一个在区间内的天,但是每一天做多能接收m个任务)
代码:
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=200005;
const int MAXE=400005;
const int INF=0X3F3F3F3F;
struct Edge
{
int to,next,cap,flow;
}edge[MAXE];
int tol;
int head[MAXN];
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
void init()
{
tol=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int w,int rw=0)
{
edge[tol].to=v;
edge[tol].cap=w;
edge[tol].next=head[u];
edge[tol].flow=0;
head[u]=tol++;
edge[tol].to=u;
edge[tol].cap=rw;
edge[tol].next=head[v];
edge[tol].flow=0;
head[v]=tol++;
}
int sap(int start,int end,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-1;
gap[0]=N;
int ans=0;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
}
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u]; i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow && dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v;
continue;
}
int Min=N;
for(int i=head[u];i!=-1;i=edge[i].next)
{
if(edge[i].cap-edge[i].flow && dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
}
gap[dep[u]]--;
if(!gap[dep[u]]) return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start) u=edge[pre[u]^1].to;
}
return ans;
}
void work()
{
int i,j,n,m,x,s,e,p,sum,sump;
scanf("%d%d",&n,&m);
sum=0;
sump=0;
init();
for(i=1;i<=n;i++)
{
scanf("%d%d%d",&p,&s,&e);
sum=max(sum,e);
sump+=p;
addedge(1,i+1,p);
for(j=s;j<=e;j++)
addedge(i+1,1+n+j,1);
}
for(i=1;i<=sum;i++)
addedge(1+n+i,2+n+sum,m);
if(sump==sap(1,2+n+sum,2+n+sum))
printf("Yes\n");
else printf("No\n");
}
int main()
{
int i,T;
scanf("%d",&T);
for(i=1;i<=T;i++)
{
printf("Case %d: ",i);
work();
printf("\n");
}
return 0;
}