LOJ#2339 通道

题意:给你三棵树,求所有点对在三棵树上的距离和中的最大值。

解:首先有个暴力,然后还有个迭代乱搞,可以得到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\n", 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\n", Ans);
36         return;
37     }
38 }
61分代码

有个部分分是只有两棵树。

我们在第一棵树上枚举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 }
46分代码

正解:这不还有一棵树吗?根据暴力写挂和情报中心的经验,我们边分治 + 虚树,即可去掉第一棵树的限制。把边分治的两部分染成不同颜色。

在第二棵树上建虚树,第三棵树上维护两种颜色的直径。

答案就用不同颜色不同集合的来更新。合并的时候每种颜色分开合并。 

  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\n", Ans);
474         return 0;
475     }
476     if(check_same()) {
477         same::solve();
478         printf("%lld\n", 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\n", Ans);
489     return 0;
490 }
AC代码

其实也不是很长......大概只有hope的一半多一点。虽然我没写hope......

 

posted @ 2019-04-16 16:28  huyufeifei  阅读(227)  评论(0编辑  收藏  举报
试着放一个广告栏(虽然没有一分钱广告费)

『Flyable Heart 応援中!』 HHG 高苗京铃 闪十PSS 双六 電動伝奇堂 章鱼罐头制作组 はきか 祝姬 星降夜