kebab (hdu 2883 网络流判满流 关键是缩点)

kebab

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1071    Accepted Submission(s): 447

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

Recommend

gaojie   |   We have carefully selected several similar problems for you:  2882 2884 3061 2888 2886

题意:有一个烧烤机,每次最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,每个烤肉所需烘烤时间为 di,注意一个烤肉可以切成几份来烤。

思路:这一题和hdu 3572 Task Schedule有一点点像,但这一题时间的范围跨度太大,不能再每个时刻看成一个点了,要进行缩点,这一点很巧妙,我没想到。将所有的到达时间和结束时间按升序排序,得到 x <= 2n-1 个时间区间。建立网络流模型:s为源,t为汇,每个顾客i作为一个结点并连边(s, i, ni*ti),每个区间j作为一个结点并连边(j, t, (ej-sj)*M),其中sj, ej分别表示区间j的起始时间和终止时间。对任意顾客i和区间j,若 [sj, ej] 完全包含在 [si,
ei] 之中,则连边(i, j, INF)。若最大流等于 ∑ni*ti 则是 Yes,否则是 No。

代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <string>
#include <map>
#include <stack>
#include <vector>
#include <set>
#include <queue>
#pragma comment (linker,"/STACK:102400000,102400000")
#define maxn 1005
#define MAXN 2005
#define mod 1000000009
#define INF 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 1e-6
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define FRE(i,a,b)  for(i = a; i <= b; i++)
#define FREE(i,a,b) for(i = a; i >= b; i--)
#define FRL(i,a,b)  for(i = a; i < b; i++)
#define FRLL(i,a,b) for(i = a; i > b; i--)
#define mem(t, v)   memset ((t) , v, sizeof(t))
#define sf(n)       scanf("%d", &n)
#define sff(a,b)    scanf("%d %d", &a, &b)
#define sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
#define pf          printf
#define DBG         pf("Hi\n")
typedef long long ll;
using namespace std;

struct Edge
{
    int u,v,cap,next;
}edge[MAXN];

int n,m,num,sum,cnt;
int level[maxn],head[maxn],cur[maxn];
int S[maxn],E[maxn],N[maxn],T[maxn],a[maxn];

void init()
{
    num=0;cnt=0;sum=0;
    mem(head,-1);
}

void addedge(int u,int v,int w)
{
    edge[num].u=u; edge[num].v=v; edge[num].cap=w; edge[num].next=head[u]; head[u]=num++;
    edge[num].u=v; edge[num].v=u; edge[num].cap=0; edge[num].next=head[v]; head[v]=num++;
}

bool bfs(int s,int t)
{
    mem(level,-1);
    level[s]=0;
    queue<int>Q;
    Q.push(s);
    while (!Q.empty())
    {
        int u=Q.front(); Q.pop();
        for (int i=head[u];i+1;i=edge[i].next)
        {
            int v=edge[i].v;
            if (level[v]==-1&&edge[i].cap>0)
            {
                level[v]=level[u]+1;
                Q.push(v);
            }
        }
    }
    return level[t]!=-1;
}

int dfs(int u,int t,int f)
{
    if (u==t) return f;
    for (int &i=cur[u];i+1;i=edge[i].next)
    {
        int v=edge[i].v;
        if (level[v]==level[u]+1&&edge[i].cap>0)
        {
            int d=dfs(v,t,min(f,edge[i].cap));
            if (d>0)
            {
                edge[i].cap-=d;
                edge[i^1].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int dinic(int s,int t,int nodenum)
{
    int flow=0,f;
    while (bfs(s,t))
    {
        for (int i=0;i<=nodenum;i++) cur[i]=head[i];
        while ((f=dfs(s,t,INF))>0)
            flow+=f;
    }
    return flow;
}

int main()
{
    int i,j;
    while (~scanf("%d%d",&n,&m))
    {
        init();
        for (i=1;i<=n;i++)
        {
            scanf("%d%d%d%d",&S[i],&N[i],&E[i],&T[i]);
            a[cnt++]=S[i];
            a[cnt++]=E[i];
            sum+=N[i]*T[i];
            addedge(0,i,N[i]*T[i]);
        }
        sort(a,a+cnt);
        cnt=unique(a,a+cnt)-a;
        for (i=0;i<cnt-1;i++)
        {
            addedge(n+i+1,n+cnt,(a[i+1]-a[i])*m);
            for (j=1;j<=n;j++)
                if (a[i]>=S[j]&&a[i+1]<=E[j])
                    addedge(j,n+i+1,INF);
        }
        int ans=dinic(0,n+cnt,n+cnt+1);
//        printf("%d\n",ans);
        if (ans==sum) printf("Yes\n");
        else printf("No\n");
    }
    return 0;
}
时间: 2024-11-05 12:32:58

kebab (hdu 2883 网络流判满流 关键是缩点)的相关文章

HDU 4292Food(网络流之最大流)

题目地址:HDU 4292 水题. 由于每个人只能有1份,所以需要拆点限制流量.建图方法为,建一源点与汇点,将食物与源点相连,权值为食物额数量,将饮料与汇点相连,权值为饮料数量..然后将人进行拆点为i和i',将对应的i与i'连边权值为1,将i与它所对应的YES的食物连边,将i'与它所对应的YES的饮料连边,一次求最大流. 代码如下: #include <iostream> #include <stdio.h> #include <string.h> #include &

HDU 2883 kebab

kebab Time Limit: 1000ms Memory Limit: 32768KB This problem will be judged on HDU. Original ID: 288364-bit integer IO format: %I64d      Java class name: Main Almost everyone likes kebabs nowadays (Here a kebab means pieces of meat grilled on a long

HDU 2883 kebab(最大流)

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

HDU 4975 (杭电多校 #10 1005题)A simple Gaussian elimination problem.(网络流之最大流)

题目地址:HDU 4975 对这题简直无语...本来以为这题要用什么更先进的方法,结果还是老方法,这么卡时间真的好吗....比赛的时候用了判环的方法,一直TLE..后来换了矩阵DP的方式,加了加剪枝就过了..无语了.. 代码如下: #include <cstdio> #include <cstring> #include <algorithm> #include <iostream> #include <cstdio> #include <

HDU 3605Escape(缩点+网络流之最大流)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3605 本来打算昨天写两道题的,结果这个题卡住了,最后才发现是最后的判断条件出错了,判断满流的条件应该是与n的比较,竟然写成与所有星球总容量的比较了.(最近大脑短路..) 这题也不是完全自己想的,没想到缩点这一技巧,由于n的数据范围太大,普通的建图方法会超时超内存,需要缩点,因为对于每个点来说,一共只有2^10种方法,而最多一共有10W个点,显然有很多点是重复的,这时可以采取缩点的方法,将重复的当成一

HDU 4888 Redraw Beautiful Drawings(最大流+判最大流网络是否唯一)

Problem Description Alice and Bob are playing together. Alice is crazy about art and she has visited many museums around the world. She has a good memory and she can remember all drawings she has seen. Today Alice designs a game using these drawings

HDU 3468 Treasure Hunting(BFS+网络流之最大流)

题目地址:HDU 3468 这道题的关键在于能想到用网络流.然后还要想到用bfs来标记最短路中的点. 首先标记方法是,对每一个集合点跑一次bfs,记录所有点到该点的最短距离.然后对于任意一对起始点来说,只要这个点到起点的最短距离+该点到终点的最短距离==起点到终点的最短距离,就说明这点在某条从起点到终点的最短路上. 然后以集合点建X集,宝物点建Y集构造二分图,将从某集合点出发的最短路中经过宝物点与该集合点连边.剩下的用二分匹配算法或最大流算法都可以.(为什么我的最大流比二分匹配跑的还要快....

HDU 3081Marriage Match II(二分+并查集+网络流之最大流)

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3081 有一段时间没写最大流的题了,这题建图居然想了好长时间...刚开始是按着最终的最大流即是做多轮数去想建图,结果根本没思路,后来想了想,可以用二分答案的思想来找最终答案.然后很明显的并查集,但是并查集学的略渣,居然卡在并查集上了..= =. 但是也不是并查集的事..是我建图的思想太正了,稍微用点逆向思维并查集就可以很好利用了. 建图思路是:建立一个源点与汇点,将女孩与源点相连,男孩与汇点相连,权值

HDU 4888 Redraw Beautiful Drawings (2014-多校3-1002,最大流,判最大流有多解)

题目: http://acm.hdu.edu.cn/showproblem.php?pid=4888 题意: 给一个n*m的矩阵的n行之和和m列之和以及限制k,使用0-k的数字填充矩阵使得其行与列之和为给定值 如果不行则输出Impossible 如果有多解则输出Not Unique 如果有一解则输出Unique,并输出构造的矩阵 方法: 最大流,判最大流有多解 1.建图: 每一行一个点,每一列一个点 源点与第i个行点连边,权值为第i行之和 第j个列点与汇点连边,权值为第j行之和 第i个行点与第j