hdoj 2883 kebab 【时间区间离散化 + 最大流】

来源:互联网 发布:java中缺省是什么意思 编辑:程序博客网 时间:2024/05/29 11:04



kebab

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


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 101 10 6 32 10 4 22 101 10 5 32 10 4 2
 

Sample Output
YesNo
 



建议先做 hdoj 3572  


看到这道题,知道要离散化,也知道怎么将时间区间离散化,但不知道怎么处理建边。o(╯□╰)o  不得不ORZ神牛了


题意:有 N 个人来吃烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ni,烤好一份肉所需时间为 ti。现在只有一台烧烤机,该机器每个单位时间能烤 M 份肉。问能否满足所有顾客的需求。


思路:先用数组rec记录所有si和ei,排序去重(离散化),保证区间不重叠。

把相邻时间区间虚拟成点,即把区间 [ rec[i], rec[i+1] ]当做一个点。

将每个人对时间点的建边处理变成对时间区间的建边处理。建好图,跑一次最大流判断是否满流即可。


建图:设置超级源点source,超级汇点sink

1,source到每个人i建边,容量为ni * ti;

2,相邻时间区间[ rec[i], rec[i+1] ] 到sink建边,容量为(rec[i+1] - rec[i]) * M,表示同时可以烤M个;

3,判断每个人的时间区间[si, ei]是否包含离散化后的相邻时间区间[ rec[i], rec[i+1] ]。若包含表示在该区间内可以提供足够的时间供给这个人烤肉,则建边容量无穷大,否则不建边。


AC代码:

#include <cstdio>#include <cstring>#include <algorithm>#include <queue>#define MAXN 800#define MAXM 200000+10#define INF 0x3f3f3f3fusing namespace std;struct Edge{    int from, to, cap, flow, next;};Edge edge[MAXM];int head[MAXN], edgenum, cur[MAXN];int dist[MAXN];bool vis[MAXN];int N, M;void init(){    edgenum = 0;    memset(head, -1, sizeof(head));}void addEdge(int u, int v, int w){    Edge E1 = {u, v, w, 0, head[u]};    edge[edgenum] = E1;    head[u] = edgenum++;    Edge E2 = {v, u, 0, 0, head[v]};    edge[edgenum] = E2;    head[v] = edgenum++;}int sumflow;//记录源点传入的总流量int source, sink;//超级源点 超级汇点struct Node{    int s, n, e, t;};Node num[210];int rec[500];void getMap(){    source = 0;    int len = 1;    sumflow = 0;    for(int i = 1; i <= N; i++)    {        scanf("%d%d%d%d", &num[i].s, &num[i].n, &num[i].e, &num[i].t);        addEdge(source, i, num[i].n * num[i].t);        sumflow += num[i].n * num[i].t;        rec[len++] = num[i].s;        rec[len++] = num[i].e;    }    sort(rec+1, rec+len);    //去重    int R = 2;    for(int i = 2; i < len; i++)//滚动数组优化        if(rec[i] != rec[i-1])            rec[R++] = rec[i];//得到R-1个端点    sort(rec+1, rec+R);    //R-1个端点 R-2个区间    sink = N+R-1;//超级汇点    for(int i = 1; i < R-1; i++)//对R-2个区间处理        addEdge(i+N, sink, (rec[i+1]-rec[i]) * M);    for(int i = 1; i <= N; i++)//对每个人的用餐时间区间 处理    {        for(int j = 1; j < R-1; j++)//枚举R-2个区间        {            if(num[i].s <= rec[j] && num[i].e >= rec[j+1])//时间容纳区间 容量无穷大                addEdge(i, j+N, INF);        }    }}bool BFS(int s, int t){    queue<int> Q;    memset(dist, -1, sizeof(dist));    memset(vis, false, sizeof(vis));    dist[s] = 0;    vis[s] = true;    Q.push(s);    while(!Q.empty())    {        int u = Q.front();        Q.pop();        for(int i = head[u]; i != -1; i = edge[i].next)        {            Edge E = edge[i];            if(!vis[E.to] && E.cap > E.flow)            {                dist[E.to] = dist[u] + 1;                if(E.to == t) return true;                vis[E.to] = true;                Q.push(E.to);            }        }    }    return false;}int DFS(int x, int a, int t){    if(x == t || a == 0) return a;    int flow = 0, f;    for(int &i = cur[x]; i != -1; i = edge[i].next)    {        Edge &E = edge[i];        if(dist[E.to] == dist[x] + 1 && (f = DFS(E.to, min(a, E.cap - E.flow), t)) > 0)        {            edge[i].flow += f;            edge[i^1].flow -= f;            flow += f;            a -= f;            if(a == 0) break;        }    }    return flow;}int Maxflow(int s, int t){    int flow = 0;    while(BFS(s, t))    {        memcpy(cur, head, sizeof(head));        flow += DFS(s, INF, t);    }    return flow;}int main(){    while(scanf("%d%d", &N, &M) != EOF)    {        init();        getMap();        if(Maxflow(source, sink) == sumflow)//满流            printf("Yes\n");        else            printf("No\n");    }    return 0;}



0 0
原创粉丝点击