【HDU】 2883 kebab(最大流+时间段离散化)

来源:互联网 发布:linux限制ip访问次数 编辑:程序博客网 时间:2024/05/21 19:42

思路:这道题目应该说看懂题意很重要。看懂之后就很简单了。

 有一个烧烤机,每个单位时间最多能烤 m 块肉,现在有 n 个人来买烤肉,每个人到达时间为 si,离开时间为 ei,点的烤肉数量为 ci,点的烤肉所需烘烤时间为 di,其实这边的ci和di有点描述的不清楚。明白一点的描述应该说的是,点的烤肉体积为ci,需要等待的时间为di。

          每个人要烤的肉可以分成若干份在同时烤,问是否存在一种方案可以满足所有顾客的需求。

这边所用到的技巧是,将时间段离散化,方法是将结束时间和开始时间一起从小到大排序,就可以得到所有的时间段。这个时间段向超级汇点走的最大流量为时间间隔dis*n(每单位时间可以烤的肉的数量)

每一个顾客可以向合适的一个时间段内走流量,最后判断总流量是否等于需求的数量就可以了。

#define _CRT_SECURE_NO_WARNINGS#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define MAXN 100010#define MAXM 400040#define INF 0x7ffffffint head[MAXN], dep[MAXN], gap[MAXN], cur[MAXN];int times[MAXN << 1];int si[MAXN], ei[MAXN], ni[MAXN], ti[MAXN];int cnt;int bit[11];int num[1025];//将情况相同的点,也就是可以到一样的行星上的人给合并成一个人,只是流量增多了.struct edge{int v;int cap;int flow;int next;}edg[MAXM];struct work{int p, s, e;}w[MAXN];void init(){cnt = 0;memset(head, -1, sizeof(head));memset(num, 0, sizeof(num));}void addedge(int u, int v, int w, int rw = 0){edg[cnt].v = v;edg[cnt].cap = w;edg[cnt].flow = 0;edg[cnt].next = head[u];head[u] = cnt++;edg[cnt].v = u;edg[cnt].cap = rw;edg[cnt].flow = 0;edg[cnt].next = head[v];head[v] = cnt++;}int Q[MAXN];void BFS(int start, int end){memset(dep, -1, sizeof(dep));memset(gap, 0, sizeof(gap));gap[0] = 1;int front = 0, rear = 0;dep[end] = 0;Q[rear++] = end;while (front != rear){int u = Q[front++];for (int i = head[u]; i != -1; i = edg[i].next){int v = edg[i].v;if (dep[v] != -1)continue;Q[rear++] = v;dep[v] = dep[u] + 1;gap[dep[v]]++;}}}int S[MAXN];int sap(int start, int end, int n){BFS(start, end);memcpy(cur, head, sizeof(head));int top = 0;int u = start;int ans = 0;while (dep[start] < n){if (u == end){int Min = INF;int inser;for (int i = 0; i < top; i++)if (Min>edg[S[i]].cap - edg[S[i]].flow){Min = edg[S[i]].cap - edg[S[i]].flow;inser = i;}for (int i = 0; i < top; i++){edg[S[i]].flow += Min;edg[S[i] ^ 1].flow -= Min;}ans += Min;top = inser;u = edg[S[top] ^ 1].v;continue;}bool flag = false;int v;for (int i = cur[u]; i != -1; i = edg[i].next){v = edg[i].v;if (edg[i].cap - edg[i].flow&&dep[v] + 1 == dep[u]){flag = true;cur[u] = i;break;}}if (flag){S[top++] = cur[u];u = v;continue;}int Min = n;for (int i = head[u]; i != -1; i = edg[i].next)if (edg[i].cap - edg[i].flow&&dep[edg[i].v] < Min){Min = dep[edg[i].v];cur[u] = i;}gap[dep[u]]--;if (!gap[dep[u]])return ans;dep[u] = Min + 1;gap[dep[u]]++;if (u != start)u = edg[S[--top] ^ 1].v;}return ans;}int Scan()//读入外挂  {int res = 0, ch, flag = 0;if ((ch = getchar()) == '-')                //判断正负  flag = 1;else if (ch >= '0' && ch <= '9')            //得到完整的数  res = ch - '0';while ((ch = getchar()) >= '0' && ch <= '9')res = res * 10 + ch - '0';return flag ? -res : res;}int main(){int n, k;while (~scanf("%d%d", &n, &k)){int cnt = 0;init();int res = 0;for (int i = 1; i <= n; i++){scanf("%d%d%d%d", &si[i], &ni[i], &ei[i], &ti[i]);times[cnt++] = si[i];times[cnt++] = ei[i];res += ni[i] * ti[i];addedge(0, i, ni[i] * ti[i]);}sort(times, times + cnt);int E = n + cnt + 2;for (int i = 0; i < cnt-1; i++)addedge(n + i + 1, E, (times[i + 1] - times[i]) * k);for (int i = 1; i <= n; i++)for (int j = 0; j < cnt;j++)if (si[i] <= times[j] && times[j + 1] <= ei[i])addedge(i, n + j + 1, INF);if (res == sap(0, E, E))puts("Yes");elseputs("No");}}


0 0
原创粉丝点击