题意:给你三棵树,求所有点对在三棵树上的距离和中的最大值。
解:首先有个暴力,然后还有个迭代乱搞,可以得到61分...
1 namespace bf { 2 inline void solve() { 3 for(int i = 1; i <= n; i++) { 4 for(int j = i; j <= n; j++) { 5 Ans = std::max(Ans, t1.dis(i, j) + t2.dis(i, j) + t3.dis(i, j)); 6 } 7 } 8 printf("%lld ", Ans); 9 return; 10 } 11 } 12 13 namespace naive { 14 inline void Rand() { 15 int x = rand() % n + 1; 16 for(int T = 1; T <= 10; T++) { 17 int y = 0; 18 LL large = -INF; 19 for(int i = 1; i <= n; i++) { 20 LL temp = t1.dis(x, i) + t2.dis(x, i) + t3.dis(x, i); 21 if(temp > large) { 22 large = temp; 23 y = i; 24 } 25 } 26 x = y; 27 Ans = std::max(Ans, large); 28 } 29 return; 30 } 31 inline void solve() { 32 for(int i = 1; i <= 10; i++) { 33 Rand(); 34 } 35 printf("%lld ", Ans); 36 return; 37 } 38 }
有个部分分是只有两棵树。
我们在第一棵树上枚举lca,那么就相当于把这些点全部挂到第二棵树上,边权是深度。此时可以用直径的性质来维护最远点对。
1 #define forson(t, x, i) for(int i = t.e[x], y = t.edge[i].v; i; i = t.edge[i].nex, y = t.edge[i].v) 2 3 inline bool check_same() { 4 std::vector<uLL> v, u; 5 for(int x = 1; x <= n; x++) { 6 v.clear(), u.clear(); 7 forson(t2, x, i) { 8 v.push_back(t2.edge[i].len * N + y); 9 } 10 forson(t3, x, i) { 11 u.push_back(t3.edge[i].len * N + y); 12 } 13 int len = v.size(); 14 if(len != u.size()) return false; 15 std::sort(v.begin(), v.end()); 16 std::sort(u.begin(), u.end()); 17 for(int i = 0; i < len; i++) { 18 if(v[i] != u[i]) return false; 19 } 20 } 21 return true; 22 } 23 24 namespace same { 25 Data data[N]; 26 inline LL exdis(const int &x, const int &y) { 27 return 2 * t2.dis(x, y) + t1.d[x] + t1.d[y]; 28 } 29 inline void merge(Data &x, const Data &y, const LL &v) { 30 int xa = x.a, xb = x.b, ya = y.a, yb = y.b; 31 LL d12 = exdis(xa, xb), d34 = exdis(ya, yb); 32 LL d13 = exdis(xa, ya), d14 = exdis(xa, yb); 33 LL d23 = exdis(xb, ya), d24 = exdis(xb, yb); 34 if(d34 > d12) { 35 d12 = d34; 36 x = y; 37 } 38 if(d13 > d12) { 39 d12 = d13; 40 x.a = xa; 41 x.b = ya; 42 } 43 if(d14 > d12) { 44 d12 = d14; 45 x.a = xa; 46 x.b = yb; 47 } 48 if(d23 > d12) { 49 d12 = d23; 50 x.a = xb; 51 x.b = ya; 52 } 53 if(d24 > d12) { 54 d12 = d24; 55 x.a = xb; 56 x.b = yb; 57 } 58 Ans = std::max(Ans, std::max(std::max(d13, d14), std::max(d23, d24)) - v); 59 return; 60 } 61 void DFS(int x, int f) { 62 data[x] = Data(x, x); 63 forson(t1, x, i) { 64 if(y == f) continue; 65 DFS(y, x); 66 merge(data[x], data[y], t1.d[x] << 1); 67 } 68 return; 69 } 70 inline void solve() { 71 DFS(1, 0); 72 return; 73 } 74 }
正解:这不还有一棵树吗?根据暴力写挂和情报中心的经验,我们边分治 + 虚树,即可去掉第一棵树的限制。把边分治的两部分染成不同颜色。
在第二棵树上建虚树,第三棵树上维护两种颜色的直径。
答案就用不同颜色不同集合的来更新。合并的时候每种颜色分开合并。
1 /** 2 * There is no end though there is a start in space. ---Infinity. 3 * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite. 4 * Only the person who was wisdom can read the most foolish one from the history. 5 * The fish that lives in the sea doesn't know the world in the land. 6 * It also ruins and goes if they have wisdom. 7 * It is funnier that man exceeds the speed of light than fish start living in the land. 8 * It can be said that this is an final ultimatum from the god to the people who can fight. 9 * 10 * Steins;Gate 11 */ 12 13 #include <bits/stdc++.h> 14 15 typedef long long LL; 16 typedef unsigned long long uLL; 17 const int N = 200010; 18 const LL INF = 4e18; 19 20 struct Edge { 21 int nex, v; 22 LL len; 23 bool vis; 24 }edge[N << 1], EDGE[N << 1]; int tp = 1, TP; 25 26 struct Data { 27 int a, b; 28 LL v; 29 Data(int A = 0, int B = 0, LL V = 0) { 30 a = A; 31 b = B; 32 v = V; 33 } 34 }data1[N], data2[N]; 35 36 int pw[N << 1], n, rdP[N], e[N], siz[N], Cnt, _n, small, root, use[N], Time, vis[N], E[N], K, imp[N], RT, col[N]; 37 LL Ans, d[N]; 38 39 struct Tree { 40 Edge edge[N << 1]; int tp = 1; 41 int e[N], pos2[N], num2, ST[N << 1][20], deep[N]; 42 LL d[N]; 43 inline void add(int x, int y, LL z) { 44 edge[++tp].v = y; 45 edge[tp].len = z; 46 edge[tp].nex = e[x]; 47 e[x] = tp; 48 return; 49 } 50 void DFS_1(int x, int f) { 51 pos2[x] = ++num2; 52 ST[num2][0] = x; 53 deep[x] = deep[f] + 1; 54 for(int i = e[x]; i; i = edge[i].nex) { 55 int y = edge[i].v; 56 if(y == f) continue; 57 d[y] = d[x] + edge[i].len; 58 DFS_1(y, x); 59 ST[++num2][0] = x; 60 } 61 return; 62 } 63 inline void prework() { 64 for(int j = 1; j <= pw[num2]; j++) { 65 for(int i = 1; i + (1 << j) - 1 <= num2; i++) { 66 if(deep[ST[i][j - 1]] < deep[ST[i + (1 << (j - 1))][j - 1]]) { 67 ST[i][j] = ST[i][j - 1]; 68 } 69 else { 70 ST[i][j] = ST[i + (1 << (j - 1))][j - 1]; 71 } 72 } 73 } 74 return; 75 } 76 inline int lca(int x, int y) { 77 x = pos2[x]; 78 y = pos2[y]; 79 if(x > y) std::swap(x, y); 80 int t = pw[y - x + 1]; 81 if(deep[ST[x][t]] < deep[ST[y - (1 << t) + 1][t]]) { 82 return ST[x][t]; 83 } 84 else { 85 return ST[y - (1 << t) + 1][t]; 86 } 87 } 88 inline LL dis(int x, int y) { 89 if(!x || !y) { 90 return -INF; 91 } 92 return d[x] + d[y] - (d[lca(x, y)] << 1); 93 } 94 inline void work() { 95 LL z; 96 for(int i = 1, x, y; i < n; i++) { 97 scanf("%d%d%lld", &x, &y, &z); 98 add(x, y, z); 99 add(y, x, z); 100 } 101 DFS_1(1, 0); 102 prework(); 103 return; 104 } 105 #undef add 106 }t1, t2, t3; 107 108 namespace bf { 109 inline void solve() { 110 for(int i = 1; i <= n; i++) { 111 for(int j = i; j <= n; j++) { 112 Ans = std::max(Ans, t1.dis(i, j) + t2.dis(i, j) + t3.dis(i, j)); 113 } 114 } 115 return; 116 } 117 } 118 119 namespace naive { 120 inline void Rand() { 121 int x = rand() % n + 1; 122 for(int T = 1; T <= 5; T++) { 123 int y = 0; 124 LL large = -INF; 125 for(int a = 1; a <= n; a++) { 126 int i = rdP[a]; 127 LL temp = t1.dis(x, i) + t2.dis(x, i) + t3.dis(x, i); 128 if(temp > large) { 129 large = temp; 130 y = i; 131 } 132 } 133 x = y; 134 Ans = std::max(Ans, large); 135 } 136 return; 137 } 138 inline void solve() { 139 for(int i = 1; i <= 5; i++) { 140 Rand(); 141 } 142 return; 143 } 144 } 145 146 namespace fire { 147 inline void Rand() { 148 int x = rand() % n + 1; 149 for(int T = 1; T <= 5; T++) { 150 int y = 0; 151 LL large = -INF; 152 for(int a = 1; a <= n; a++) { 153 int i = rdP[a]; 154 LL temp = t1.dis(x, i) + t2.dis(x, i) + t3.dis(x, i); 155 if(temp > large) { 156 large = temp; 157 y = i; 158 } 159 else if(rand() % 100 < T) { 160 large = temp; 161 y = i; 162 } 163 } 164 x = y; 165 Ans = std::max(Ans, large); 166 } 167 return; 168 } 169 inline void solve() { 170 for(int i = 1; i <= 5; i++) { 171 Rand(); 172 } 173 return; 174 } 175 } 176 177 #define forson(t, x, i) for(int i = t.e[x], y = t.edge[i].v; i; i = t.edge[i].nex, y = t.edge[i].v) 178 179 inline bool check_same() { 180 std::vector<uLL> v, u; 181 for(int x = 1; x <= n; x++) { 182 v.clear(), u.clear(); 183 forson(t2, x, i) { 184 v.push_back(t2.edge[i].len * N + y); 185 } 186 forson(t3, x, i) { 187 u.push_back(t3.edge[i].len * N + y); 188 } 189 int len = v.size(); 190 if(len != u.size()) return false; 191 std::sort(v.begin(), v.end()); 192 std::sort(u.begin(), u.end()); 193 for(int i = 0; i < len; i++) { 194 if(v[i] != u[i]) return false; 195 } 196 } 197 return true; 198 } 199 200 namespace same { 201 Data data[N]; 202 inline LL exdis(const int &x, const int &y) { 203 return 2 * t2.dis(x, y) + t1.d[x] + t1.d[y]; 204 } 205 inline void merge(Data &x, const Data &y, const LL &v) { 206 int xa = x.a, xb = x.b, ya = y.a, yb = y.b; 207 LL d12 = exdis(xa, xb), d34 = exdis(ya, yb); 208 LL d13 = exdis(xa, ya), d14 = exdis(xa, yb); 209 LL d23 = exdis(xb, ya), d24 = exdis(xb, yb); 210 if(d34 > d12) { 211 d12 = d34; 212 x = y; 213 } 214 if(d13 > d12) { 215 d12 = d13; 216 x.a = xa; 217 x.b = ya; 218 } 219 if(d14 > d12) { 220 d12 = d14; 221 x.a = xa; 222 x.b = yb; 223 } 224 if(d23 > d12) { 225 d12 = d23; 226 x.a = xb; 227 x.b = ya; 228 } 229 if(d24 > d12) { 230 d12 = d24; 231 x.a = xb; 232 x.b = yb; 233 } 234 Ans = std::max(Ans, std::max(std::max(d13, d14), std::max(d23, d24)) - v); 235 return; 236 } 237 void DFS(int x, int f) { 238 data[x] = Data(x, x); 239 forson(t1, x, i) { 240 if(y == f) continue; 241 DFS(y, x); 242 merge(data[x], data[y], t1.d[x] << 1); 243 } 244 return; 245 } 246 inline void solve() { 247 DFS(1, 0); 248 return; 249 } 250 } 251 252 #undef forson 253 254 inline void add(int x, int y, LL z) { 255 edge[++tp].v = y; 256 edge[tp].len = z; 257 edge[tp].nex = e[x]; 258 e[x] = tp; 259 return; 260 } 261 262 inline void ADD(int x, int y) { 263 EDGE[++TP].v = y; 264 EDGE[TP].nex = E[x]; 265 E[x] = TP; 266 return; 267 } 268 269 void rebuild(int x, int f) { 270 int temp = 0; 271 for(int i = t1.e[x]; i; i = t1.edge[i].nex) { 272 int y = t1.edge[i].v; 273 LL len = t1.edge[i].len; 274 if(y == f) continue; 275 if(!temp) { 276 add(x, y, len); 277 add(y, x, len); 278 temp = x; 279 } 280 else if(!t1.edge[i].nex) { 281 add(temp, y, len); 282 add(y, temp, len); 283 } 284 else { 285 add(temp, ++Cnt, 0); 286 add(Cnt, temp, 0); 287 temp = Cnt; 288 add(temp, y, len); 289 add(y, temp, len); 290 } 291 rebuild(y, x); 292 } 293 return; 294 } 295 296 void getroot(int x, int f) { 297 siz[x] = 1; 298 for(int i = e[x]; i; i = edge[i].nex) { 299 int y = edge[i].v; 300 if(y == f || edge[i].vis) continue; 301 getroot(y, x); 302 siz[x] += siz[y]; 303 if(std::max(siz[y], _n - siz[y]) < small) { 304 small = std::max(siz[y], _n - siz[y]); 305 root = i; 306 } 307 } 308 return; 309 } 310 311 inline void work(int x) { 312 if(use[x] == Time) return; 313 use[x] = Time; 314 E[x] = col[x] = 0; 315 return; 316 } 317 318 void DFS_1(int x, int f, int flag) { 319 siz[x] = 1; 320 if(x <= n) { 321 work(x); 322 imp[++K] = x; 323 col[x] = flag; 324 } 325 for(int i = e[x]; i; i = edge[i].nex) { 326 int y = edge[i].v; 327 if(y == f || edge[i].vis) continue; 328 d[y] = d[x] + edge[i].len; 329 DFS_1(y, x, flag); 330 siz[x] += siz[y]; 331 } 332 return; 333 } 334 335 inline bool cmp(const int &a, const int &b) { 336 return t2.pos2[a] < t2.pos2[b]; 337 } 338 339 inline void build_t() { 340 static int stk[N], top; 341 std::sort(imp + 1, imp + K + 1, cmp); 342 K = std::unique(imp + 1, imp + K + 1) - imp - 1; 343 stk[top = 1] = imp[1]; 344 for(int i = 2; i <= K; i++) { 345 int x = imp[i], y = t2.lca(x, stk[top]); 346 work(y); 347 while(top > 1 && t2.pos2[y] <= t2.pos2[stk[top - 1]]) { 348 ADD(stk[top - 1], stk[top]); 349 top--; 350 } 351 if(stk[top] != y) { 352 ADD(y, stk[top]); 353 stk[top] = y; 354 } 355 stk[++top] = x; 356 } 357 while(top > 1) { 358 ADD(stk[top - 1], stk[top]); 359 top--; 360 } 361 RT = stk[top]; 362 return; 363 } 364 365 inline bool operator < (const Data &a, const Data &b) { 366 return a.v < b.v; 367 } 368 369 inline LL exdis(int x, int y) { 370 return t3.dis(x, y) + d[x] + d[y] + t2.d[x] + t2.d[y]; 371 } 372 373 inline void merge(Data &x, const Data &y) { 374 int xa = x.a, xb = x.b, ya = y.a, yb = y.b; 375 LL d12 = exdis(xa, xb), d34 = exdis(ya, yb); 376 LL d13 = exdis(xa, ya), d14 = exdis(xa, yb); 377 LL d23 = exdis(xb, ya), d24 = exdis(xb, yb); 378 if(d34 > d12) { 379 d12 = d34; 380 x = y; 381 } 382 if(d13 > d12) { 383 d12 = d13; 384 x.a = xa; 385 x.b = ya; 386 } 387 if(d14 > d12) { 388 d12 = d14; 389 x.a = xa; 390 x.b = yb; 391 } 392 if(d23 > d12) { 393 d12 = d23; 394 x.a = xb; 395 x.b = ya; 396 } 397 if(d24 > d12) { 398 x.a = xb; 399 x.b = yb; 400 } 401 return; 402 } 403 404 inline void merge(int x, int y, LL v) { 405 int p1 = data1[x].a, p2 = data1[x].b, p3 = data2[x].a, p4 = data2[x].b; 406 int p5 = data1[y].a, p6 = data1[y].b, p7 = data2[y].a, p8 = data2[y].b; 407 /// cal ans 408 Ans = std::max(Ans, std::max(std::max(exdis(p1, p7), exdis(p1, p8)), std::max(exdis(p2, p7), exdis(p2, p8))) + v); 409 Ans = std::max(Ans, std::max(std::max(exdis(p3, p5), exdis(p3, p6)), std::max(exdis(p4, p5), exdis(p4, p6))) + v); 410 /// update data1[x] data2[x] 411 merge(data1[x], data1[y]); 412 merge(data2[x], data2[y]); 413 return; 414 } 415 416 void DFS_2(int x, LL v) { 417 data1[x] = data2[x] = Data(0, 0); 418 if(col[x] == 1) { 419 data1[x] = Data(x, x); 420 } 421 else if(col[x] == 2) { 422 data2[x] = Data(x, x); 423 } 424 for(int i = E[x]; i; i = EDGE[i].nex) { 425 int y = EDGE[i].v; 426 DFS_2(y, v); 427 merge(x, y, v - (t2.d[x] << 1)); 428 } 429 return; 430 } 431 432 void e_div(int x) { 433 if(_n == 1) { 434 return; 435 } 436 small = N; 437 getroot(x, 0); 438 edge[root].vis = edge[root ^ 1].vis = 1; 439 x = edge[root].v; 440 int y = edge[root ^ 1].v; 441 442 ++Time; 443 d[x] = d[y] = K = TP = 0; 444 DFS_1(x, 0, 1); 445 DFS_1(y, 0, 2); 446 build_t(); 447 DFS_2(RT, edge[root].len); 448 449 /// 450 _n = siz[x]; 451 e_div(x); 452 _n = siz[y]; 453 e_div(y); 454 return; 455 } 456 457 int main() { 458 459 srand(15); 460 scanf("%d", &n); 461 for(int i = 2; i <= 2 * n; i++) { 462 pw[i] = pw[i >> 1] + 1; 463 } 464 for(int i = 1; i <= n; i++) { 465 rdP[i] = i; 466 } 467 std::random_shuffle(rdP + 1, rdP + n + 1); 468 t1.work(); 469 t2.work(); 470 t3.work(); 471 /*if(n <= 3000) { 472 bf::solve(); 473 printf("%lld ", Ans); 474 return 0; 475 } 476 if(check_same()) { 477 same::solve(); 478 printf("%lld ", Ans); 479 return 0; 480 } 481 naive::solve(); 482 fire::solve();*/ 483 /// --------------------------- 484 Cnt = n; 485 rebuild(1, 0); 486 _n = Cnt; 487 e_div(1); 488 printf("%lld ", Ans); 489 return 0; 490 }
其实也不是很长......大概只有hope的一半多一点。虽然我没写hope......