【题意】
有一个烤肉机,每次可以同时烤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 }