题解:
题意为由M台机器,处理N个事件,每个事件有开始时间结束时间和处理时长。每台机器在一个时间只能处理一个事件,每个事件可以分为很多段,由不同的机器进行处理。求N个事件能不能顺利处理完。
构图:
将N个事件为这位1-N个点,因为E<=500,可以将时间分为500个点,源点1,事件点2-N+1,时间点为N+2 - N+500+1,汇点为n = N+500+2。将原点与所有事件点建边,权值为Pi,将所有事件点与所有能处理该事件的时间点建边,权值为1,因为一个时间只能处理一个事件一个时间单位部分,将所有时间点与汇点建边,权值为M,因为每个时间点都有M台机器可用。
然后用SAP或者Dinic跑最大流
AC code
//Max_flow
//@2018/05/04 Friday
//SAP O(n^2 * m) O(m*3*2)
//by Tawn
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int INF = 0x3f3f3f3f;
const int maxn = 1000 + 100;
const int maxm = 1000000 + 10;
int n,m;
int head[maxn];//链式前向星
int tot = 0;
int Pi[maxn];
int Si[maxn];
int Ti[maxn];
struct edge
{
int to;
int c;
int next;
edge(int x = 0, int y = 0, int z = 0) : to(x), c(y), next(z) {}
}es[maxm*2];//记录边 注意是2倍
void add_edge(int u, int v, int c)
{
es[tot] = edge(v,c,head[u]);
head[u] = tot++;
}
int SAP(int s, int t)
{
int numh[maxn],h[maxn],ce[maxn],pre[maxn];
//numh 记录gap优化的统计高度数量数组,h 距离标号数组,ce 当前弧,pre前驱数组
int f, ans = 0, u, temp, neck, i; //初始化最大流为0
memset(h,0,sizeof(h));
memset(numh,0,sizeof(numh));
memset(pre,-1,sizeof(pre));
for(i = 1; i <= n; i++) ce[i] = head[i];
numh[0] = n;
u = s;
while(h[s] < n)
{
//寻找增广路
if(u == t)
{
f = INF;
for(i = s; i != t; i = es[ce[i]].to)
{
if(f > es[ce[i]].c)
{
neck = i;
f = es[ce[i]].c;
}
}
for(i = s; i != t; i = es[ce[i]].to)
{
temp = ce[i];
es[temp].c -= f;
es[temp^1].c += f;
}
ans += f;
u = neck;
}
//寻找可行弧
for(i = ce[u]; i != -1; i = es[i].next)
if(es[i].c && h[u] == h[es[i].to] + 1) break;
//寻找增广路
if(i != -1)
{
ce[u] = i;
pre[es[i].to] = u;
u = es[i].to;
}
else
{
if(!--numh[h[u]]) break; //gap optimization
ce[u] = head[u];
for(temp = n, i = head[u]; i != -1; i = es[i].next)
if(es[i].c) temp = min(temp, h[es[i].to]);
h[u] = temp + 1;
++numh[h[u]];
if(u != s) u = pre[u];//重标号并且从当前点前驱重新增广
}
}
return ans;
}
int main()
{
int T;
scanf("%d",&T);
int t = T;
while(T--)
{
int N,M;
scanf("%d%d",&N,&M);
tot = 0;
memset(head,-1,sizeof(head));
int sp = 0;
for(int i = 1; i <= N; i++) {scanf("%d%d%d",&Pi[i],&Si[i],&Ti[i]); sp += Pi[i];}
n = 2 + N + 500;
for(int i = 2; i < N+2; i++)
{
add_edge(1,i,Pi[i-1]);
add_edge(i,1,0);
}
for(int i = N+2; i < n; i++)
{
add_edge(i,n,M);
add_edge(n,i,0);
}
for(int i = 2; i < N+2; i++)
{
for(int j = Si[i-1]; j <= Ti[i-1]; j++)
{
add_edge(i,j+N+1,1);
add_edge(j+N+1,i,0);
}
}
int ans = SAP(1,n);
//cout << ans << endl;
if(ans == sp) printf("Case %d: Yes\n",t - T);
else printf("Case %d: No\n",t - T);
cout << endl;
}
return 0;
}