题意:和hdu 3572相似,不同的是这里是n个人来,要从si时间开始,ei时间前结束,共有ni个肉串,每个肉串烤cost个单位时间。
所以处理时候与hdu3572略不同的是讲一整个时间区间先离散,作为一个点,如果某人的起始和结束时间包含某个时间区间,说明那个人在这个区间里面能烤任意时间(当然前提是不超过这个区间长度,比如某段时间区间长度为10,那个人可以烤0~10的任意时间),所以将那个人的任务与该时间点连边,容量控制为inf。其他的处理和3572那题是一样的
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define pi acos(-1.0)
#define eps 1e-8
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 1000;
struct node{
int v, w, nxt;
int cap;
}e[N*N];
int head[N];
int pre[N];
int dep[N];
int gap[N];
int cur[N];
int tot[N];
int n, m, nn;
int cnt, ccnt, x;
int s[N], t[N];
int st, ed;
void init()
{
st = cnt = 0;
memset( head, -1, sizeof( head ) );
}
void add( int u, int v, int w, int rw = 0 )
{
e[cnt].v = v;
e[cnt].w = 0;
e[cnt].cap = w;
e[cnt].nxt = head[u];
head[u] = cnt++;
e[cnt].v = u;
e[cnt].w = 0;
e[cnt].cap = rw;
e[cnt].nxt = head[v];
head[v] = cnt++;
}
int sap()
{
memset( dep, 0, sizeof( dep ) );
memset( gap, 0, sizeof( gap ) );
memcpy( cur, head, sizeof( head ) );
int u = st;
pre[u] = -1;
int flow = 0;
nn = ed + 1;
gap[0] = nn;
while( dep[st] < nn )
{
if( u == ed )
{
int minn = inf;
for( int i = pre[u]; ~i; i = pre[e[i^1].v] )
minn = min( minn, e[i].cap - e[i].w );
for( int i = pre[u]; ~i; i = pre[e[i^1].v] )
{
e[i].w += minn;
e[i^1].w -= minn;
}
u = st;
flow += minn;
}
bool f = 0;
for( int i = cur[u]; ~i; i = e[i].nxt )
{
int v = e[i].v;
if( dep[v] + 1 == dep[u] && e[i].cap - e[i].w > 0 )
{
f = 1;
cur[u] = pre[v] = i;
u = v;
break;
}
}
if( f )
continue;
int minn = nn;
for( int i = head[u]; ~i; i = e[i].nxt )
{
if( minn > dep[e[i].v] && e[i].cap - e[i].w > 0 )
{
cur[u] = i;
minn = dep[e[i].v];
}
}
gap[dep[u]]--;
if( !gap[dep[u]] )
break;
dep[u] = minn + 1;
gap[dep[u]]++;
if( u != st )
u = e[pre[u]^1].v;
}
return flow;
}
int main()
{
while( ~scanf("%d%d", &n, &m) )
{
init();
int ni, cost;
ccnt = 0;
x = 1;
int sum = 0;
for( int i = 1; i <= n; ++i )
{
scanf("%d%d%d%d", &s[i], &ni, &t[i], &cost);
add( st, i, cost * ni );
sum += cost * ni;
tot[++ccnt] = s[i];
tot[++ccnt] = t[i];
}
tot[0] = 0;
sort( tot+1, tot + ccnt + 1 );
for( int i = 2; i <= ccnt; ++i )
{
if( tot[x] != tot[i] )
tot[++x] = tot[i];
}
ed = x + n + 1;
for( int i = 1; i <= x; ++i ) // seg
{
int tmp = tot[i] - tot[i-1];
add( i+n, ed, tmp * m );
for( int j = 1; j <= n; ++j ) //task
{
if( s[j] <= tot[i-1] && tot[i] <= t[j] )
add( j, i+n, inf );
}
}
int ans = sap();
if( ans == sum )
puts("Yes");
else
puts("No");
}
return 0;
}
dinic过不了去学isap,姿势没学对一直T。。最后换成sap真是不容易