• 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
    " , 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
    " , res);
    87         }
    88     }
    89 }
  • 相关阅读:
    制作自适应布局的模块及框架(转载)
    从今天起开始写博了
    工作中碰到的css问题解决方法
    标题写个什么好呢
    快速编写HTML(Zen conding)
    2013年1月21日记事
    opc 方面研究
    关于 部署方面研究 Visual Studio 2013
    intel AVX指令集
    关于 返回数据类型 后 加& 的作用
  • 原文地址:https://www.cnblogs.com/Recoder/p/5513374.html
Copyright © 2020-2023  润新知