HDU 2883 kebab(最大流)

【题意】

有一个烤肉机,每次可以同时烤M份肉。有N个顾客,第i个顾客li时刻到达,ri时刻走, 点了ai份肉,每份肉需要bi的时间烤,客人的每份肉可以分开烤,比如一份肉需要t时间烤,如果平均分出t份,那么能在1个时间内烤完。问能否满足所有顾客的需求。

【分析】

烤肉机相当于每个单位时间段都在工作,可以一直往里面加肉,每个单位时间段最多可以容下M份肉。对于每个客人,其需求需要在(li,ri)的区间内完成,因为烤肉可以分开烤,则只需考虑单位份烤肉所需时间然后累加,即只用考虑ai*bi <=(ri - li)*M,如果满足,那么这个顾客是可以满足的。显然,问题转化为区间覆盖问题。

线段上每个单位线段的容量为M,每个顾客的区间为(li,ri),其顾客容量为ai*bi。求能否覆盖完

【建图】

由以上分析,可以由源点到每个顾客i连边,容量为ai*bi;由每个单位时间段向汇点连边,容量为M;每个顾客i对每个时间段j连边,容量为INF.跑最大流判定即可。但是时间点有100W个,不可行。

【离散化】把时间点离散化成很多个区间,最多2*N-1 个区间。每个区间j,向汇点连边(ri - li)*M。每个顾客i向每个区间j连边,如果顾客的时间段覆盖了区间,容量为INF.

【Mark】注意建图一共有600+点,这里导致WA 2发。

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<math.h>
  4 #include<algorithm>
  5 
  6 using namespace std;
  7 
  8 #define INF 1e8
  9 #define MAX_VECT 605
 10 #define MAX_EDGE 2200000
 11 
 12 /************************************************************************/
 13 /*    Name: dinic
 14 /*  Description: Find the max flow of the network from start to
 15                  end point
 16 /*  Variable Description: to[] - end point of the current edge
 17                           next[] - the next edge which also comes from
 18                                    the same point as current edge
 19                           cap[] - the capability of the current edge
 20                           v[] - the first edge index which comes from the
 21                                 the current point
 22                           d[] - the layer number of current point
 23 /************************************************************************/
 24 
 25 
 26 int to[MAX_EDGE], next[MAX_EDGE], cap[MAX_EDGE], tot;
 27 int v[MAX_VECT], d[MAX_VECT], queue[MAX_VECT], n;
 28 int S, T;
 29 inline void single_insert(int _u, int _v, int var)
 30 {
 31     to[tot] = _v;
 32     cap[tot] = var;
 33     next[tot] = v[_u];
 34     v[_u] = tot++;
 35 }
 36 
 37 void insert(int from, int to,  int cap)
 38 {
 39     single_insert(from, to, cap);
 40     single_insert(to, from, 0);
 41 }
 42 
 43 bool bfs_initial()
 44 {
 45     memset(d, -1, sizeof(d));
 46     int bg, ed, x, y;
 47     bg = ed = d[S] = 0;
 48     queue[ed++] = S;
 49     while (bg < ed)
 50     {
 51         x = queue[bg++];
 52         for (int i = v[x]; i+1; i = next[i])
 53         {
 54             y = to[i];
 55             if (cap[i] && d[y] == -1)
 56             {
 57                 d[y] = d[x] + 1;
 58                 if (y == T) return true;
 59                 queue[ed++] = y;
 60             }
 61         }
 62     }
 63     return false;
 64 }
 65 
 66 int Find(int x, int low = INF)
 67 {
 68     if (x == T) return low;
 69     int ret, y, ans = 0;
 70     for (int i = v[x]; (i+1) && low; i = next[i])
 71     {
 72         y = to[i];
 73         if (cap[i] && d[y] == d[x] + 1 && (ret = Find(y, min(low, cap[i]))))
 74         {
 75             cap[i] -= ret;
 76             cap[i^1] += ret;
 77             low -= ret;
 78             ans += ret;
 79         }
 80     }
 81     return ans;
 82 }
 83 int dinic()
 84 {
 85     int ans = 0;
 86     while (bfs_initial())
 87         ans += Find(S);
 88     return ans;
 89 }
 90 
 91 
 92 int dinicc()
 93 {
 94     int ans = 0;
 95     while(bfs_initial())
 96     {
 97         int edge, x, y, back, iter = 1;
 98         while(iter)
 99         {
100             x = (iter == 1) ? S : to[queue[iter - 1]];
101             if (x == T)
102             {
103                 int minE, minCap = INF;
104                 for (int i = 1; i < iter; i++)
105                 {
106                     edge = queue[i];
107                     if (cap[edge] < minCap)
108                     {
109                         minCap = cap[edge];
110                         back = i;
111                     }
112                 }
113                 for (int i = 1; i < iter; i++)
114                 {
115                     edge = queue[i];
116                     cap[edge] -= minCap;
117                     cap[edge ^ 1] += minCap;
118                 }
119                 ans += minCap;
120                 iter = back;
121             }
122             else
123             {
124                 for (edge = v[x]; edge + 1; edge = next[edge])
125                 {
126                     y = to[edge];
127                     if (cap[edge] && d[y] == d[x] + 1)
128                         break;
129                 }
130                 if (edge+1)
131                     queue[iter++] = edge;
132                 else
133                 {
134                     d[x] = -1;
135                     iter--;
136                 }
137             }
138         }
139     }
140     return ans;
141 }
142 int m;
143 struct time{
144     int l,r;
145     int a,b;
146 }seq[MAX_VECT];
147 int ttt[MAX_VECT*2];
148 int cnt = 0;
149 
150 int check(int L,int R,int l,int r)
151 {
152     return (L<=l && r<=R);
153 }
154 int main()
155 {
156     while (scanf("%d%d",&n,&m)==2)
157     {
158         tot = 0;
159         memset(v,-1,sizeof(v));
160         cnt = 0;
161         for (int i=1;i<=n;i++)
162         {
163             scanf("%d%d%d%d",&seq[i].l,&seq[i].a,&seq[i].r,&seq[i].b);
164             ttt[++cnt] = seq[i].l;
165             ttt[++cnt] = seq[i].r;
166         }
167         sort(ttt+1,ttt+1+cnt);
168 
169         S = 0;
170         T = n + cnt;
171         int sum = 0;
172         for (int i=1;i<=n;i++)
173         {
174             insert(S,i,seq[i].a*seq[i].b);
175             sum += seq[i].a * seq[i].b;
176         }
177         for (int i=1;i<cnt;i++)
178         {
179             insert(n+i,T,(ttt[i+1] - ttt[i])*m);
180         }
181         for (int i=1;i<=n;i++)
182             for (int j=1;j<cnt;j++)
183             {
184                 if (check(seq[i].l, seq[i].r, ttt[j],ttt[j+1]))
185                 {
186                     insert(i,n+j,INF);
187                 }
188             }
189 
190         n = n + cnt;
191 
192         int ans = dinic();
193         if (ans == sum)
194             printf("Yes\n");
195         else
196             printf("No\n");
197     }
198     return 0;
199 }
hdu2883

 

 

转载于:https://www.cnblogs.com/wangsouc/articles/3296621.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值