而後題意大概就是m只老鼠,而後吃n個奶酪,已知ios
要求c++
老鼠吃奶酪的時間能夠爲小數,且一個老鼠「一輩子」能夠吃多塊奶酪,一塊奶酪「一輩子」能夠屢次被吃git
如今你能夠爲奶酪$+T\ s$,也就是對於全部奶酪$t_i += T$網絡
如今讓你最小化$T$spa
<!--瞎BB開始-->code
好像機房就我沒寫了......blog
反正是要看題解的,這輩子逃不開題解的......排序
但題解看不懂連生活都維持不了這樣子......
<!--瞎BB結束-->get
仍是DL不能依靠,仍是本身看比較好博客
二分答案+最大流
建圖方式:
首先對全部時間點離散化,記兩個時間點之間的時間段長度爲$tim$,而後把老鼠從大到小排序最後加個數字0,差分獲得m個差分值,記爲d,依次編號爲$1,2,3...$
對奶酪建點,對時間點間的時間段拆點,拆成m個老鼠差分值
源點連向奶酪,容量 p
奶酪連向奶酪保質期內的時間段的老鼠差分點,容量爲 老鼠差分值*時間段長度
老鼠差分點連向終點,容量爲 老鼠差分值*時間段長度*老鼠差分點編號(排序後從大到小)
而後跑最大流,奶酪滿流即爲合法
下面配合一個實例來說解證實爲何這樣是對的(反正我是想不到的)
爲了區分老鼠速度和差分後的速度,咱們將拆出來的點稱爲「老鼠差分點「或」老鼠點「或指代意義的」點「
舉個例子
老鼠分別有速度7,4,2
差分獲得3,2,2
而後咱們假設時間段長度爲2
而後老鼠到t的流量限制爲6,8,12
而後和奶酪的流量限制爲6,4,4
當且僅當這張圖全部奶酪到起點的邊滿流的時候有解,其中若是一個老鼠$x$在一個時間段內吃了奶酪$y$,那麼從該時間段$m-x$到$m$的老鼠差分點到奶酪$y$都會有流量$t*d_i$。這張圖的工做原理是比較簡單的(若是看不懂能夠參考一下其它DL的博客)
最主要難以證實的是題目須要知足的兩個要求。
首先證實這張圖知足一個老鼠同一時間只吃一個奶酪
若是一個從大到小排名第$k$的老鼠吃了同一時間段的$x$塊奶酪(若是不在同一時間段的話就不會有非法狀態,若是有重疊則重疊部分和這個問題等價),設第$i$塊奶酪吃了時間$t_i$,那麼咱們假設一個非法狀態,也就是$(\Sigma{t_i}) > tim$,也就是一個老鼠同時吃多塊奶酪,因此這個時候k號老鼠差分點產生的流量至少爲$\Sigma{(t_i)}*d_k$,咱們記爲流量,可是咱們對該老鼠的限制有$k*tim*d_k$,咱們記爲容量,咱們要證實非法狀態的$流量 > 容量$,在網絡流中不存在。
這個時候咱們有兩種狀況:
而後證實這張圖知足一個奶酪同時只被一隻老鼠吃
這個比較簡單,同樣假設一共有x只老鼠吃了奶酪,每個吃了時間$t_i$,而後假設非法狀態$(\Sigma{t_i}) > tim$,而後因爲排名靠前的老鼠吃了的話那麼在差分點中對排名較後的老鼠也會有時間上的影響,也就是吃了同一個奶酪的排名最後的老鼠流量爲$\Sigma{(t_i)}*d_k$,大於邊的容量$ti*d_k$,因此狀態不存在。
代碼以下:
1 #include <cstdio> 2 #include <cctype> 3 #include <cstring> 4 #include <iostream> 5 6 //User's Lib 7 8 #include <cmath> 9 #include <algorithm> 10 11 using namespace std; 12 13 #define DEBUG_PORT 14 #define DEBUG 15 16 #ifdef ONLINE_JUDGE 17 #undef DEBUG_PORT 18 #undef DEBUG 19 #endif 20 21 #ifdef DEBUG_PORT 22 #if __cplusplus >= 201103L 23 #ifdef DEBUG 24 template<typename T> 25 extern inline void Debug(T tar){ 26 cerr << tar << endl; 27 } 28 template<typename Head, typename T, typename... Tail> 29 extern inline void Debug(Head head, T mid, Tail... tail){ 30 cerr << head << ' '; 31 Debug(mid, tail...); 32 } 33 #else 34 # pragma GCC diagnostic push 35 # pragma GCC diagnostic ignored "-Wunused-parameter" 36 template<typename Head, typename T, typename... Tail> 37 extern inline void Debug(Head head, T mid, Tail... tail){ 38 return ; 39 } 40 # pragma GCC diagnostic pop 41 # pragma message "Warning : pragma used" 42 #endif 43 #else 44 # pragma message "Warning : C++11 Not Use" 45 #ifdef DEBUG 46 template <typename T> 47 extern inline void Debug(T tar){ 48 cerr << tar << endl; 49 } 50 #else 51 # pragma GCC diagnostic push 52 # pragma GCC diagnostic ignored "-Wunused-parameter" 53 template <typename T> 54 extern inline void Debug(T tar){ 55 return ; 56 } 57 # pragma GCC diagnostic pop 58 # pragma message "Warning : pragma used" 59 #endif 60 #endif 61 #else 62 # pragma GCC diagnostic push 63 # pragma GCC diagnostic ignored "-Wunused-parameter" 64 template<typename Head, typename T, typename... Tail> 65 extern inline void Debug(Head head, T mid, Tail... tail){ 66 return ; 67 } 68 template <typename T> 69 extern inline void Debug(T tar){ 70 return ; 71 } 72 # pragma GCC diagnostic pop 73 # pragma message "Warning : pragma used" 74 #endif 75 76 char buf[11111111], *pc = buf; 77 78 extern inline void Main_Init(){ 79 static bool INITED = false; 80 if(INITED) fclose(stdin), fclose(stdout); 81 else { 82 fread(buf, 1, 11111111, stdin); 83 INITED = true; 84 } 85 } 86 87 static inline int read(){ 88 int num = 0; 89 char c, sf = 1; 90 while(isspace(c = *pc++)); 91 if(c == 45) sf = -1, c = *pc ++; 92 while(num = num * 10 + c - 48, isdigit(c = *pc++)); 93 return num * sf; 94 } 95 96 namespace LKF{ 97 template <typename T> 98 extern inline T abs(T tar){ 99 return tar < 0 ? -tar : tar; 100 } 101 template <typename T> 102 extern inline void swap(T &a, T &b){ 103 T t = a; 104 a = b; 105 b = t; 106 } 107 template <typename T> 108 extern inline void upmax(T &x, const T &y){ 109 if(x < y) x = y; 110 } 111 template <typename T> 112 extern inline void upmin(T &x, const T &y){ 113 if(x > y) x = y; 114 } 115 template <typename T> 116 extern inline T max(T a, T b){ 117 return a > b ? a : b; 118 } 119 template <typename T> 120 extern inline T min(T a, T b){ 121 return a < b ? a : b; 122 } 123 } 124 125 //Source Code 126 127 const int MAXK = 33; 128 const int MAXN = 2018; 129 const int MAXM = 99999; 130 const double INF = 1e16; 131 const double eps = 1e-6; 132 133 inline bool comp(const double &a, const double &b){ 134 double tmp = a - b;//int??? 135 if(fabs(tmp) < eps) return 0; 136 return a > b ? 1 : -1; 137 } 138 139 int s = MAXN - 10, t = s + 1; 140 141 struct Queue{ 142 int s, t; 143 int q[MAXN]; 144 Queue(){s = 1, t = 0;} 145 inline void clear(){ 146 s = 1, t = 0; 147 } 148 inline bool empty(){ 149 return s > t; 150 } 151 inline int size(){ 152 return t - s + 1; 153 } 154 inline void push(int tar){ 155 q[++ t] = tar; 156 } 157 inline int front(){ 158 return q[s]; 159 } 160 inline void pop(){ 161 s ++; 162 } 163 }; 164 165 struct Graph{ 166 int tot; 167 int beginx[MAXN], endx[MAXM], nxt[MAXM]; 168 double res[MAXM]; 169 Graph(){ 170 tot = 1; 171 } 172 inline void Init(){ 173 tot = 1; 174 memset(beginx, 0, sizeof(beginx)); 175 } 176 inline void add_edge(int u, int v, double r){ 177 // Debug(u, "->", v, "[label = \"", r, "\"]");//Debug... 178 nxt[++ tot] = beginx[u], beginx[u] = tot, endx[tot] = v, res[tot] = r; 179 nxt[++ tot] = beginx[v], beginx[v] = tot, endx[tot] = u, res[tot] = 0; 180 } 181 }; 182 183 struct ISap{ 184 Graph g; 185 Queue mession; 186 double max_f; 187 int cur[MAXN], d[MAXN], num[MAXN], pre[MAXN]; 188 inline void bfs(){ 189 mession.clear(); 190 mession.push(t); 191 memset(d, 0, sizeof(d)); 192 memset(num, 0, sizeof(num)); 193 d[t] = 1; 194 int u, v; 195 while(!mession.empty()){ 196 u = mession.front(); 197 mession.pop(); 198 num[d[u]] ++; 199 for(int i = g.beginx[u]; i; i = g.nxt[i]){ 200 v = g.endx[i]; 201 if(!d[v] && comp(g.res[i ^ 1], 0)){ 202 d[v] = d[u] + 1; 203 mession.push(v); 204 } 205 } 206 } 207 } 208 inline double dfs(int u, double now_f){ 209 if(u == t) return now_f; 210 double ret_f = 0; 211 for(int &i = cur[u]; i; i = g.nxt[i]){ 212 int v = g.endx[i]; 213 if(comp(g.res[i], 0) && d[u] == d[v] + 1){ 214 double ret = dfs(v, min(g.res[i], now_f)); 215 ret_f += ret, now_f -= ret; 216 g.res[i] -= ret, g.res[i ^ 1] += ret; 217 if(d[s] >= MAXN - 4 || !comp(now_f, 0)) return ret_f; 218 } 219 } 220 if(-- num[d[u]] == 0) d[s] = MAXN - 4; 221 ++ num[++ d[u]]; 222 cur[u] = g.beginx[u]; 223 return ret_f; 224 } 225 inline double ISAP(){ 226 bfs(); 227 max_f = 0; 228 memcpy(cur, g.beginx, sizeof(cur)); 229 while(d[s] < MAXN - 5) 230 max_f += dfs(s, INF); 231 return max_f; 232 } 233 }isap; 234 235 int n, m, sum; 236 int p[MAXK], r[MAXK], d[MAXK], ss[MAXK]; 237 double tmp_arr[MAXK << 1]; 238 int cnt; 239 240 inline bool check(double tar){ 241 cnt = 0; 242 isap.g.Init(); 243 for(int i = 1; i <= n; i++) 244 tmp_arr[++ cnt] = r[i], tmp_arr[++ cnt] = d[i] + tar; 245 sort(tmp_arr + 1, tmp_arr + 1 + cnt); 246 cnt = unique(tmp_arr + 1, tmp_arr + 1 + cnt) - tmp_arr - 1; 247 for(int i = 1; i <= n; i++) 248 isap.g.add_edge(s, i, p[i]); 249 for(int i = 2; i <= cnt; i++){ 250 double lst = tmp_arr[i - 1], tim = tmp_arr[i] - lst; 251 for(int j = 1; j <= m; j++) 252 isap.g.add_edge(n + (i - 2) * m + j, t, j * tim * ss[j]); 253 for(int j = 1; j <= n; j++) 254 if(r[j] <= lst && d[j] + tar >= tmp_arr[i]) 255 for(int k = 1; k <= m; k++) 256 isap.g.add_edge(j, n + (i - 2) * m + k, tim * ss[k]); 257 } 258 return !comp(isap.ISAP(), sum); 259 } 260 261 int main(){ 262 Main_Init(); 263 int T = read(); 264 while(T --){ 265 n = read(), m = read(); 266 sum = 0; 267 for(int i = 1; i <= n; i++) 268 sum += (p[i] = read()), r[i] = read(), d[i] = read(); 269 for(int i = 1; i <= m; i++) 270 ss[i] = read(); 271 ss[m + 1] = 0; 272 int tmp = ss[1]; 273 sort(ss + 1, ss + 1 + m, greater<int>()); 274 for(int i = 1; i <= m; i++) 275 ss[i] -= ss[i + 1]; 276 double l = 0, r = 1.0 * sum / tmp, mid; 277 while(fabs(r - l) > eps){ 278 mid = (l + r) / 2.0; 279 if(check(mid)) r = mid; 280 else l = mid; 281 } 282 printf("%.5lf\n", mid); 283 } 284 Main_Init(); 285 return 0; 286 }