n位顾客要找老板烤肉串,第i个人要烤
Ni
串,每串烤
Ti
分钟,可以分成几个部分来烤,但是必须在
Si
之后才能开始烤,而且必须在
Ei
之前烤完(个人认为题目描述不清,应该是时间区间
(Si,Ei]
)。烤炉每分钟可以同时烤m单位的肉串(也就是说,每个人要烤肉的总量是
Ni∗Ti
单位)。问是否能够满足所有顾客的需求。
1≤N≤200,1≤M≤1000,1≤Ni,Ti≤50,1≤Si<Ei≤1,000,000
这道题类似于HDU3572 Task Schedule,只是建图的方式不同。
传送门:http://acm.hdu.edu.cn/showproblem.php?pid=3572
题解:http://blog.youkuaiyun.com/cqbzwja/article/details/50877048
这道题不能像上面那道题一样把时间分成1分钟的小段,因为
106
太大。我们需要按照所有人的起始和终止时间排序把时间分段,一个段的时间算一个节点,这样最多只会有400个时间点。
源点s向每个人连边,容量为
Ni∗Si
表示需要烤的总单位;每个人向对应的时间区间连边,即所有的时间段j满足
[Sj,Ei]⊆[Si,Ei]
,至于时间段j是什么,看我的代码就懂了;每个时间段向汇点连容量为
(Ej−Sj)∗M
的边,表示这段时间中烤肉的最大单位数。
最后求出最大流。比较
∑ni=1Ni∗Si
与
maxflow
的大小。
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
#define MAXN 100010
#define INF 0x3f3f3f3f
using namespace std;
inline int Min(int a,int b)
{return a<b?a:b;}
struct E
{
int v,w,op;
E(){}
E(int a,int b,int c)
{v = a; w = b; op = c;}
};
vector<E> g[MAXN];
int d[MAXN],vd[MAXN],s,t,ni[MAXN],ti[MAXN],si[MAXN],ei[MAXN];
int N,M,cnt,table[MAXN],flow,sum;
int aug(int i,int augco)
{
int augc = augco,j,mind = t-1,delta,sz = g[i].size();
if(i == t) return augco;
for(j = 0; j < sz; j++)
{
int v = g[i][j].v;
if(g[i][j].w)
{
if(d[i] == d[v]+1)
{
delta = Min(augc,g[i][j].w);
delta = aug(v,delta);
g[i][j].w -= delta;
g[v][g[i][j].op].w += delta;
augc -= delta;
if(d[s] >= t) return augco - augc;
if(augc == 0) break;
}
if(d[v] < mind) mind = d[v];
}
}
if(augc == augco)
{
vd[d[i]]--;
if(vd[d[i]] == 0) d[s] = t;
d[i] = mind+1;
vd[d[i]]++;
}
return augco-augc;
}
void sap()
{
memset(d,0,sizeof d);
memset(vd,0,sizeof vd);
flow = 0;
vd[0] = t;
while(d[s] < t)
flow += aug(s,INF);
}
void init()
{
for(int i = 1; i <= N; i++)
ni[i] = ti[i] = si[i] = ei[i] = 0;
for(int i = 1; i <= t; i++)
g[i].clear();
memset(table,0,sizeof table);
cnt = sum = 0;
}
int main()
{
while(scanf("%d%d",&N,&M) != EOF)
{
s = N+1;
for(int i = 1; i <= N; i++)
{
scanf("%d%d%d%d",&si[i],&ni[i],&ei[i],&ti[i]);
table[++cnt] = si[i];
table[++cnt] = ei[i];
sum += ni[i]*ti[i];
g[s].push_back(E(i,ni[i]*ti[i],g[i].size()));
g[i].push_back(E(s,0,g[s].size()-1));
}
sort(table+1,table+cnt+1);
int len = unique(table+1,table+cnt+1) - (table+1);
t = s+len+1;
for(int i = 1; i <= N; i++)
for(int j = 2; j <= len; j++)
if(si[i] <= table[j-1]&&ei[i] >= table[j])
{
int x = s+j-1;
g[i].push_back(E(x,INF,g[x].size()));
g[x].push_back(E(i,0,g[i].size()-1));
}
for(int i = 2; i <= len; i++)
{
int x = s+i-1;
g[x].push_back(E(t,(table[i]-table[i-1])*M,g[t].size()));
g[t].push_back(E(x,0,g[x].size()-1));
}
sap();
if(flow == sum) printf("Yes\n");
else printf("No\n");
init();
}
}