HDU 2586 How far away ? (LCA)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586

LCA模版题。

RMQ+LCA:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 
 6 using namespace std;
 7 const int MAXN = 4e4 + 100;
 8 typedef pair<int , int>P;
 9 vector <P> G[MAXN];
10 int dep[MAXN] , dis[MAXN] , par[MAXN][20] , ok[MAXN];
11 
12 void init(int n) {
13     for(int i = 1 ; i <= n ; i++) {
14         G[i].clear();
15         ok[i] = 0;
16     }
17 }
18 
19 void dfs(int root) {
20     for(int i = 0 ; i < G[root].size() ; i++) {
21         dis[G[root][i].first] = dis[root] + G[root][i].second;
22         dfs(G[root][i].first);
23     }
24 }
25 
26 void dfs2(int u , int p , int d) {
27     dep[u] = d;
28     par[u][0] = p;
29     for(int i = 0 ; i < G[u].size() ; i++) {
30         dfs2(G[u][i].first , u , d + 1);
31     }
32 }
33 
34 int lca(int u , int v) {
35     if(dep[u] < dep[v]) {
36         swap(u , v);
37     }
38     for(int k = 0 ; k < 16 ; k++) {
39         if((dep[u] - dep[v]) >> k & 1) {
40             u = par[u][k];
41         }
42     }
43     if(u == v)
44         return u;
45     for(int k = 15 ; k >= 0 ; k--) {
46         if(par[u][k] != par[v][k]) {
47             u = par[u][k];
48             v = par[v][k];
49         }
50     }
51     return par[u][0];
52 }
53 
54 int main()
55 {
56     int n , m , q , v , u , d , root , t;
57     char op[10];
58     scanf("%d" , &t);
59     while(t--) {
60         scanf("%d %d" , &n , &m);
61         init(n);
62         root = (n + 1) * n / 2;
63         for(int i = 0 ; i < n - 1 ; i++) {
64             scanf("%d %d %d" , &u , &v , &d);
65             G[u].push_back(P(v , d));
66             if(!ok[v]) {
67                 root -= v;
68                 ok[v] = 1;
69             }
70         }
71         dfs2(root , -1 , 0);
72         dis[root] = 0;
73         for(int k = 0 ; k < 16 ; k++) {
74             for(int i = 1 ; i <= n ; i++) {
75                 if(par[i][k] <= 0) {
76                     par[i][k + 1] = 0;
77                 }
78                 else {
79                     par[i][k + 1] = par[par[i][k]][k];
80                 }
81             }
82         }
83         dfs(root);
84         for(int i = 0 ; i < m ; i++) {
85             scanf("%d %d" , &u , &v);
86             printf("%d\n" , dis[u] + dis[v] - 2 * dis[lca(u , v)]);
87         }
88     }
89 }

 

树链剖分的LCA:

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 using namespace std;
 5 const int MAXN = 5e4 + 10;
 6 struct data {
 7     int to , next , cost;
 8 }edge[MAXN << 1];
 9 int head[MAXN] , cnt;
10 int par[MAXN] , dep[MAXN] , top[MAXN] , id[MAXN] , dis[MAXN] , size[MAXN] , son[MAXN];
11 
12 void init() {
13     memset(head , -1 , sizeof(head));
14     cnt = 0;
15 }
16 
17 inline void add(int u , int v , int cost) {
18     edge[cnt].to = v;
19     edge[cnt].next = head[u];
20     edge[cnt].cost = cost;
21     head[u] = cnt++;
22 }
23 //求size , par , son , dep
24 void dfs_1(int u , int p , int d) {
25     par[u] = p , size[u] = 1 , son[u] = u , dep[u] = d;
26     for(int i = head[u] ; ~i ; i = edge[i].next) {
27         int v = edge[i].to;
28         if(v == p)
29             continue;
30         dis[v] = dis[u] + edge[i].cost; //离根的距离
31         dfs_1(v , u , d + 1);
32         if(size[v] > size[son[u]]) //取重儿子
33             son[u] = v;
34         size[u] += size[v];
35     }
36 }
37 //求top , id
38 void dfs_2(int u , int p , int t) { //p为父节点 t为链的祖先
39     top[u] = t; //链的祖先
40     id[u] = ++cnt; //点的顺序
41     if(son[u] != u) //重儿子优先
42         dfs_2(son[u] , u , t);
43     for(int i = head[u] ; ~i ; i = edge[i].next) {
44         int v = edge[i].to;
45         if(v == p || v == son[u])
46             continue;
47         dfs_2(v , u , v); //树链重新开始
48     }
49 }
50 //树链剖分求lca的复杂度是(nlognlogn),建议用RMQ求lca
51 int lca(int u , int v) {
52     int fu = top[u] , fv = top[v];
53     while(top[u] != top[v]) { //链是否相同,不同就循环
54         if(dep[fu] < dep[fv]) { //比较两个链的深度
55             v = par[fv];
56             fv = top[fv];
57         }
58         else {
59             u = par[fu];
60             fu = top[u];
61         }
62     }
63     if(dep[u] >= dep[v]) //在相同的链上
64         return v;
65     return u;
66 }
67 
68 int main()
69 {
70     int n , q , u , v , cost , x , y , z , t;
71     scanf("%d" , &t);
72     while(t--) {
73         scanf("%d %d" , &n , &q);
74         init();
75         for(int i = 1 ; i < n ; ++i) {
76             scanf("%d %d %d" , &u , &v , &cost);
77             add(u , v , cost);
78             add(v , u , cost);
79         }
80         cnt = 0;
81         dfs_1(1 , 1 , 0);
82         dfs_2(1 , 1 , 1);
83         while(q--) {
84             scanf("%d %d" , &x , &y);
85             int res = (dis[x] + dis[y] - 2 * dis[lca(x , y)]);
86             printf("%d\n" , res);
87         }
88     }
89 }

 

posted @ 2016-05-20 20:36  Recoder  阅读(175)  评论(0编辑  收藏  举报