码迷,mamicode.com
首页 > 其他好文 > 详细

树链剖分

时间:2015-04-15 22:55:26      阅读:193      评论:0      收藏:0      [点我收藏+]

标签:

先来LCA的:

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <cstring>
 5 #include <cmath>
 6 #define REP(i, s, n) for(int i = s; i <= n; i ++)
 7 #define RAP(i, n, s) for(int i = n; i >= s; i --)
 8 using namespace std;
 9 const int maxn = 200000 + 10;
10 int fch[maxn], ms = 1; struct Tedge { int x, y, next; } adj[maxn * 2]; //我c 我c 我c 我c 我c 我c TAT!!!!!!!!!! Σ( ° △ °|||)︴
11 int dep[maxn], top[maxn], fa[maxn], son[maxn], s[maxn], n, m;
12 inline void read(int &x){
13     x = 0; int sig = 1; char ch = getchar();
14     while(!isdigit(ch)) { if(ch == -) sig = -1; ch = getchar(); }
15     while(isdigit(ch)) x = 10 * x + ch - 0, ch = getchar();
16     x *= sig; return ;
17 }
18 inline void write(int x){
19     if(x == 0) { putchar(0); return ; }
20     if(x < 0) putchar(-), x = -x;
21     int len = 0, buf[20];
22     while(x) buf[len ++] = x % 10, x /= 10;
23     RAP(i, len - 1, 0) putchar(buf[i] + 0); return ;
24 }
25 void AddEdge(int u, int v){
26     adj[ms] = (Tedge){ u, v, fch[u] }; fch[u] = ms ++;
27     adj[ms] = (Tedge){ v, u, fch[v] }; fch[v] = ms ++;
28     return ;
29 }
30 void First_DFS(int x){
31     s[x] = 1; dep[x] = dep[fa[x]] + 1;
32     for(int i = fch[x]; i; i = adj[i].next){
33         int v = adj[i].y;
34         if(v != fa[x]){ // // // // // // // // // // // // // // // // // // // //
35             fa[v] = x;//记得先认亲!!!!!!! 
36             First_DFS(v);
37             if(s[v] > s[son[x]]) son[x] = v; //更新重链
38             s[x] += s[v];
39         }
40     }
41     return ;
42 }
43 void Second_DFS(int x, int tp){
44     top[x] = tp;//在重链上行走
45     if(son[x]) Second_DFS(son[x], tp);//有重边,继续顺着走
46     for(int i = fch[x]; i; i = adj[i].next){//更新其他轻边 
47         int v = adj[i].y;
48         if(v != fa[x] && v != son[x]) Second_DFS(v, v); //一定不顺着重边走,更新tp再往下。
49     }
50     return ;
51 }
52 void LCA(int& a, int& b){
53     int f1 = top[a], f2 = top[b];
54     while(f1 != f2){
55         if(dep[f1] < dep[f2]) swap(f1, f2), swap(a, b);//如果f2拉后腿了就换f2上! 
56         a = fa[f1]; f1 = top[a];//跨过轻边的阻碍,上重链高速。 
57     }
58     return ;
59 }
60 int dist(int a, int b){
61     int ans = dep[a] + dep[b]; LCA(a, b); return ans - min(dep[a], dep[b]) * 2;//得看后面的人不是前面的人,要乘二。 
62 }
63 void init(){
64     read(n); read(m); int u, v, S = 1;
65     REP(i, 1, n - 1) read(u), read(v), AddEdge(u, v);
66     First_DFS(S); Second_DFS(S, S);
67     return ;
68 }
69 void work(){
70     int a, b, c, d[3];
71     while(m --){
72         read(a); read(b); read(c);
73         d[0] = dist(a, b);
74         d[1] = dist(b, c);
75         d[2] = dist(a, c);
76         sort(d, d + 3);
77         write(d[1]); putchar(\n);
78     }
79     return ;
80 }
81 void print(){
82 
83     return ;
84 }
85 int main(){
86     init();
87     work();
88     print();
89     return 0;
90 }

 

树链剖分

标签:

原文地址:http://www.cnblogs.com/chxer/p/4430370.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!