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 14 /* Name: dinic 15 /* Description: Find the max flow of the network from start to 16 end point 17 /* Variable Description: to[] - end point of the current edge 18 next[] - the next edge which also comes from 19 the same point as current edge 20 cap[] - the capability of the current edge 21 v[] - the first edge index which comes from the 22 the current point 23 d[] - the layer number of current point 24 /************************************************************************/ 25 26 27 int to[MAX_EDGE], next[MAX_EDGE], cap[MAX_EDGE], tot; 28 int v[MAX_VECT], d[MAX_VECT], queue[MAX_VECT], n; 29 int S, T; 30 inline void single_insert(int _u, int _v, int var) 31 { 32 to[tot] = _v; 33 cap[tot] = var; 34 next[tot] = v[_u]; 35 v[_u] = tot++; 36 } 37 38 void insert(int from, int to, int cap) 39 { 40 single_insert(from, to, cap); 41 single_insert(to, from, 0); 42 } 43 44 bool bfs_initial() 45 { 46 memset(d, -1, sizeof(d)); 47 int bg, ed, x, y; 48 bg = ed = d[S] = 0; 49 queue[ed++] = S; 50 while (bg < ed) 51 { 52 x = queue[bg++]; 53 for (int i = v[x]; i+1; i = next[i]) 54 { 55 y = to[i]; 56 if (cap[i] && d[y] == -1) 57 { 58 d[y] = d[x] + 1; 59 if (y == T) return true; 60 queue[ed++] = y; 61 } 62 } 63 } 64 return false; 65 } 66 67 int Find(int x, int low = INF) 68 { 69 if (x == T) return low; 70 int ret, y, ans = 0; 71 for (int i = v[x]; (i+1) && low; i = next[i]) 72 { 73 y = to[i]; 74 if (cap[i] && d[y] == d[x] + 1 && (ret = Find(y, min(low, cap[i])))) 75 { 76 cap[i] -= ret; 77 cap[i^1] += ret; 78 low -= ret; 79 ans += ret; 80 } 81 } 82 return ans; 83 } 84 int dinic() 85 { 86 int ans = 0; 87 while (bfs_initial()) 88 ans += Find(S); 89 return ans; 90 } 91 92 93 int dinicc() 94 { 95 int ans = 0; 96 while(bfs_initial()) 97 { 98 int edge, x, y, back, iter = 1; 99 while(iter) 100 { 101 x = (iter == 1) ? S : to[queue[iter - 1]]; 102 if (x == T) 103 { 104 int minE, minCap = INF; 105 for (int i = 1; i < iter; i++) 106 { 107 edge = queue[i]; 108 if (cap[edge] < minCap) 109 { 110 minCap = cap[edge]; 111 back = i; 112 } 113 } 114 for (int i = 1; i < iter; i++) 115 { 116 edge = queue[i]; 117 cap[edge] -= minCap; 118 cap[edge ^ 1] += minCap; 119 } 120 ans += minCap; 121 iter = back; 122 } 123 else 124 { 125 for (edge = v[x]; edge + 1; edge = next[edge]) 126 { 127 y = to[edge]; 128 if (cap[edge] && d[y] == d[x] + 1) 129 break; 130 } 131 if (edge+1) 132 queue[iter++] = edge; 133 else 134 { 135 d[x] = -1; 136 iter--; 137 } 138 } 139 } 140 } 141 return ans; 142 } 143 int m; 144 struct time{ 145 int l,r; 146 int a,b; 147 }seq[MAX_VECT]; 148 int ttt[MAX_VECT*2]; 149 int cnt = 0; 150 151 int check(int L,int R,int l,int r) 152 { 153 return (L<=l && r<=R); 154 } 155 int main() 156 { 157 while (scanf("%d%d",&n,&m)==2) 158 { 159 tot = 0; 160 memset(v,-1,sizeof(v)); 161 cnt = 0; 162 for (int i=1;i<=n;i++) 163 { 164 scanf("%d%d%d%d",&seq[i].l,&seq[i].a,&seq[i].r,&seq[i].b); 165 ttt[++cnt] = seq[i].l; 166 ttt[++cnt] = seq[i].r; 167 } 168 sort(ttt+1,ttt+1+cnt); 169 170 S = 0; 171 T = n + cnt; 172 int sum = 0; 173 for (int i=1;i<=n;i++) 174 { 175 insert(S,i,seq[i].a*seq[i].b); 176 sum += seq[i].a * seq[i].b; 177 } 178 for (int i=1;i<cnt;i++) 179 { 180 insert(n+i,T,(ttt[i+1] - ttt[i])*m); 181 } 182 for (int i=1;i<=n;i++) 183 for (int j=1;j<cnt;j++) 184 { 185 if (check(seq[i].l, seq[i].r, ttt[j],ttt[j+1])) 186 { 187 insert(i,n+j,INF); 188 } 189 } 190 191 n = n + cnt; 192 193 int ans = dinic(); 194 if (ans == sum) 195 printf("Yes\n"); 196 else 197 printf("No\n"); 198 } 199 return 0; 200 }
/****
Author:wangsouc
****/
【推荐】博客园的心动:当一群程序员决定开源共建一个真诚相亲平台
【推荐】开源 Linux 服务器运维管理面板 1Panel V2 版本正式发布
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步