hdu 2883(构图+最大流+压缩区间)

kebab

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1603    Accepted Submission(s): 677

Problem Description

Almost
everyone likes kebabs nowadays (Here a kebab means pieces of meat
grilled on a long thin stick). Have you, however, considered about the
hardship of a kebab roaster while enjoying the delicious food? Well,
here‘s a chance for you to help the poor roaster make sure whether he
can deal with the following orders without dissatisfying the customers.

Now
N customers is coming. Customer i will arrive at time si (which means
the roaster cannot serve customer i until time si). He/She will order ni
kebabs, each one of which requires a total amount of ti unit time to
get it well-roasted, and want to get them before time ei(Just at exactly
time ei is also OK). The roaster has a big grill which can hold an
unlimited amount of kebabs (Unbelievable huh? Trust me, it’s real!). But
he has so little charcoal that at most M kebabs can be roasted at the
same time. He is skillful enough to take no time changing the kebabs
being roasted. Can you help him determine if he can meet all the
customers’ demand?

Oh, I forgot to say that the roaster needs not
to roast a single kebab in a successive period of time. That means he
can divide the whole ti unit time into k (1<=k<=ti) parts such
that any two adjacent parts don’t have to be successive in time. He can
also divide a single kebab into k (1<=k<=ti) parts and roast them
simultaneously. The time needed to roast one part of the kebab well is
linear to the amount of meat it contains. So if a kebab needs 10 unit
time to roast well, he can divide it into 10 parts and roast them
simultaneously just one unit time. Remember, however, a single unit time
is indivisible and the kebab can only be divided into such parts that
each needs an integral unit time to roast well.

Input

There
are multiple test cases. The first line of each case contains two
positive integers N and M. N is the number of customers and M is the
maximum kebabs the grill can roast at the same time. Then follow N lines
each describing one customer, containing four integers: si (arrival
time), ni (demand for kebabs), ei (deadline) and ti (time needed for
roasting one kebab well).

There is a blank line after each input block.

Restriction:
1 <= N <= 200, 1 <= M <= 1,000
1 <= ni, ti <= 50
1 <= si < ei <= 1,000,000

Output

If the roaster can satisfy all the customers, output “Yes” (without quotes). Otherwise, output “No”.

Sample Input

2 10
1 10 6 3
2 10 4 2

2 10
1 10 5 3
2 10 4 2

Sample Output

Yes
No

Source

2009 Multi-University Training Contest 9 - Host by HIT

题意:

有不多于200个任务,每个任务要在si到ei这个时间段内完成,每个任务的任务量是ti*ni,只有一台机器,且其单位时间内可完成的任务量为m。现在问能否使所有的任务全部在规定的时间段内完成。

题解:这个题和之前做的一道任务分配的题很相似,但是那道题是将区间拆成一个个点拿出来,这个题点数太多是不行的,所以我们将区间排序,去重之后再加边,先从超级源点向每个人连ni*ti的边,然后每个人能够等待的时间区间连一条容量为INF的边,最后所有的时间区间都向汇点连一条(time[i]-time[i-1])*m的边,做最大流,如果max_flow==sum(ni*ti),那么这个这么多任务就是可以完成的.

#include<iostream>
#include<cstdio>
#include<cstring>
#include <algorithm>
#include <math.h>
#include <queue>
using namespace std;
const int N = 1005;
const int INF = 999999999;
struct Edge{
    int v,w,next;
}edge[N*N];
int head[N];
int level[N];
int tot;
void init()
{
    memset(head,-1,sizeof(head));
    tot=0;
}
void addEdge(int u,int v,int w,int &k)
{
    edge[k].v = v,edge[k].w=w,edge[k].next=head[u],head[u]=k++;
    edge[k].v = u,edge[k].w=0,edge[k].next=head[v],head[v]=k++;
}
int BFS(int src,int des)
{
    queue<int>q;
    memset(level,0,sizeof(level));
    level[src]=1;
    q.push(src);
    while(!q.empty())
    {
        int u = q.front();
        q.pop();
        if(u==des) return 1;
        for(int k = head[u]; k!=-1; k=edge[k].next)
        {
            int v = edge[k].v;
            int w = edge[k].w;
            if(level[v]==0&&w!=0)
            {
                level[v]=level[u]+1;
                q.push(v);
            }
        }
    }
    return -1;
}
int dfs(int u,int des,int increaseRoad){
    if(u==des||increaseRoad==0) return increaseRoad;
    int ret=0;
    for(int k=head[u];k!=-1;k=edge[k].next){
        int v = edge[k].v,w=edge[k].w;
        if(level[v]==level[u]+1&&w!=0){
            int MIN = min(increaseRoad-ret,w);
            w = dfs(v,des,MIN);
            if(w > 0)
            {
                edge[k].w -=w;
                edge[k^1].w+=w;
                ret+=w;
                if(ret==increaseRoad) return ret;
            }
            else level[v] = -1;
            if(increaseRoad==0) break;
        }
    }
    if(ret==0) level[u]=-1;
    return ret;
}
int Dinic(int src,int des)
{
    int ans = 0;
    while(BFS(src,des)!=-1) ans+=dfs(src,des,INF);
    return ans;
}
int n,m;
int s[N],num[N],e[N],t[N];
int time[N];
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF){
        init();
        int k = 0;
        int sum = 0;
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d",&s[i],&num[i],&e[i],&t[i]);
            sum += num[i]*t[i];
            time[++k] = s[i];
            time[++k] = e[i];
        }
        sort(time+1,time+k+1);
        int cnt = 1;
        for(int i=2;i<=k;i++){
            if(time[i]==time[i-1]) continue;
            time[++cnt] = time[i];
        }
        int src = 0,des = n+cnt+1;
        for(int i=1;i<=n;i++){
            addEdge(src,i,num[i]*t[i],tot);
        }
        for(int i=1;i<=n;i++){
            for(int j=1;j<=cnt;j++){
                if(s[i]<=time[j-1]&&time[j]<=e[i]){
                    addEdge(i,n+j,INF,tot);
                }
            }
        }
        for(int i=1;i<=cnt;i++){
            addEdge(n+i,des,(time[i]-time[i-1])*m,tot);
        }
        if(Dinic(src,des)==sum) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
时间: 2024-08-26 18:18:18

hdu 2883(构图+最大流+压缩区间)的相关文章

HDU 3572 【最大流 &amp;&amp; 时间区间建图】

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5398    Accepted Submission(s): 1742 Problem Description Our geometry princess XMM has stoped her study in computational geometry t

hdu 3572(构图+最大流)

Task Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7015    Accepted Submission(s): 2192 Problem Description Our geometry princess XMM has stoped her study in computational geometry to

HDU 2883 kebab(最大流)

HDU 2883 kebab 题目链接 题意:有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,每个烤肉所需烘烤时间为 di,注意一个烤肉可以切成几份来烤 思路:把区间每个点存起来排序后,得到最多2 * n - 1个区间,这些就表示几个互相不干扰的时间,每个时间内只可能有一个任务器做,这样建模就简单了,源点连向汇点,容量为任务需要总时间,区间连向汇点,容量为区间长度,然后每个任务如果包含了某个区间,之间就连边容量无限大

K - Leapin&#39; Lizards - HDU 2732(最大流)

题意:在一个迷宫里面有一些蜥蜴,这个迷宫有一些柱子组成的,并且这些柱子都有一个耐久值,每当一只蜥蜴跳过耐久值就会减一,当耐久值为0的时候这个柱子就不能使用了,每个蜥蜴都有一个最大跳跃值d,现在想知道有多少蜥蜴不能离开迷宫(跳出迷宫就可以离开了.) 输入描述:输入矩阵的行M和跳跃值D,接着输入两个矩阵(列数自己求),第一个矩阵是每个柱子的耐久值,下面一个矩阵有'L'的表示这个柱子上有一只蜥蜴. 分析:题目明白还是比较容易的,矩阵的点数是20*20,也就400个点,对每个有耐久值的柱子进行拆点,然后

HDU 4883 TIANKENG’s restaurant (区间更新)

Problem Description TIANKENG manages a restaurant after graduating from ZCMU, and tens of thousands of customers come to have meal because of its delicious dishes. Today n groups of customers come to enjoy their meal, and there are Xi persons in the

hdu 3217 Health(状态压缩DP)

Health Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 527    Accepted Submission(s): 145 Problem Description Unfortunately YY gets ill, but he does not want to go to hospital. His girlfriend LM

HDU 4283 You Are the One 区间dp

题意: 题意好复杂... 给定n个人,从左到右排好队. 他们依次从左到右离开队伍. 每个人有个权值d 当某个人是第k-th离开队伍的,那么不开心值为 d*(k-1) 有一个操作,对于一个子序列,可以把前面一段翻转. 问最小的不开心值和. #include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> #include<vector> #include<q

HDU 1885 Key Task 状态压缩+搜索

点击打开链接 Key Task Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1176    Accepted Submission(s): 462 Problem Description The Czech Technical University is rather old - you already know that it c

HDU 4862 Jump 费用流

又是一个看了题解以后还坑了一天的题…… 结果最后发现是抄代码的时候少写了一个负号. 题意: 有一个n*m的网格,其中每个格子上都有0~9的数字.现在你可以玩K次游戏. 一次游戏是这样定义的: 你可以选任意之前没有走过的格子作为起点.然后走任意步,其中每一步你可以向右或者向下走任意格.假如从(x1, y1)走到(x2, y2)需要花费能量|x1-x2|+|y1-y2|-1,如果这一步和上一步格子的数字相同,那么可以获得格子上相应数字的能量.能量可以为负值. 问你,在K次以内走完所以格子最多能得到多