【HDU 2586】LCA模板

在一棵树上 求2个点的最短距离。那么首先利用LCA找到2个点的近期公共祖先

公式:ans = dis(x) + dis(y) - 2 * dis(lca(x,y))

这里的dis(x)指的上x距离根节点的距离

注意一些细节方面,比方数组的越界问题:

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn = 45555;
struct Edge{
    int to;
    LL  dist;
    Edge(int to,LL dist):to(to),dist(dist){};
};
int n,m;
int deep[maxn],pa[maxn][22];
LL  dis[maxn];
vector<Edge>G[maxn];
void init(){
    memset(pa,-1,sizeof(pa));
    for(int i = 1; i <= n; i++) G[i].clear();
}
//----------------LAC---------------------------
void dfs(int pos,int d,LL dist){
    //printf("[%d %d]\n",pos,dist);
    deep[pos] = d;
    dis[pos] = dist;
    int Size = G[pos].size();
    for(int i = 0; i < Size; i++)
        dfs(G[pos][i].to,d + 1,dist + G[pos][i].dist);
}
void lca_init(){
    for(int j = 1; (1 << j) <= n; j++)
        for(int i = 1; i <= n; i++)
            if(pa[i][j - 1] != -1)
                pa[i][j] = pa[pa[i][j - 1]][j - 1];
}
int lca(int a,int b){
    if(a == b)
        return a;
    if(deep[a] < deep[b])   swap(a,b);
    int i;
    for(i = 0;(1 << i) <= deep[a]; i++);
    for(int j = i; j >= 0; j--)
        if(pa[a][j] != -1 && deep[pa[a][j]] >= deep[b])
            a = pa[a][j];
    if(a == b)
        return b;
    for(int j = i; j >= 0; j--)
        if(pa[a][j] != -1 && deep[pa[a][j]] != deep[pa[b][j]]){
            a = pa[a][j];
            b = pa[b][j];
        }
    return pa[a][0];
}
//-------------------------------------------------
int main(){
    int T;
    scanf("%d",&T);
    while(T--){
        scanf("%d%d",&n,&m);
        int x,y,z;
        init();
        for(int i = 0; i < n - 1; i++){
            scanf("%d%d%d",&x,&y,&z);
            G[x].push_back(Edge(y,z));
            pa[y][0] = x;
        }
        for(int i = 1; i <= n; i++)if(pa[i][0] == -1){
            dfs(i,0,0);
            break;
        }
        lca_init();
        for(int i = 0; i < m; i++){
            scanf("%d%d",&x,&y);
            LL ans = dis[x] + dis[y] - 2 * dis[lca(x,y)];
            printf("%I64d\n",ans);
        }
    }
    return 0;
}
时间: 2024-08-04 19:31:26

【HDU 2586】LCA模板的相关文章

hdu 2586 LCA模板题(离线算法)

http://acm.hdu.edu.cn/showproblem.php?pid=2586 Problem Description There are n houses in the village and some bidirectional roads connecting them. Every day peole always like to ask like this "How far is it if I want to go from house A to house B&quo

HDU 2586 LCA模板题

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2586 题目大意:在一个无向树上,求一条链权和. 解题思路: 0 | 1 /   \ 2      3 设dist[i]为i到根0的链和,求法(Dfs过程中dist[v]=dist[u]+e[i].w) 对于树中任意两点形成的链,可以通过LCA最近公共祖先剖分. 比如2->3,就可以经过LCA点1:  2->1->3 链和=dist[u]+dist[v]-2*dist[LCA[u,v]] (

HDU 2586 LCA

LCA模板题. DFS记录好,到根结点的距离. #include <bits/stdc++.h> using namespace std; const int maxn = 40000+5; const int logmaxn = 20; struct Edge { int to,w; }; std::vector<Edge> G[maxn]; int f[maxn],dis[maxn],deep[maxn],p[maxn][20],n; struct LCA { int n; i

HDU 2586 LCA离线算法 tarjan算法

LCA tarjan算法模板题 题意:给一个无根树,有q个询问,每个询问两个点,问两点的距离. 用tarjan离线算法算出每个询问的两点的最近公共祖先 ans[i]=dis[x[i]]+dis[y[i]]-2*dis[z[i]]; //  x[i],y[i]分别存储每次询问的两点,z[i]存储这两点的最近公共祖先 #include "stdio.h" #include "string.h" int tot,n,m; int f[40010],x[40010],y[4

HDU 2586 LCA转RMQ

点击打开链接 题意:就是问两个节点间的距离 思路:又切了一道模版水题,不解释了,看不懂变量含义的可以看我写的这篇,解释的比较详细ZOJ 3195 #include <vector> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> #include <algorithm> using namespace std; typedef

hdu 2586(LCA+并查集)

How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6734    Accepted Submission(s): 2498 Problem Description There are n houses in the village and some bidirectional roads connecting

HDU 2586 How far away ? (LCA最近公共祖先)

题目地址:HDU 2586 LCA第一发. 纯模板题. 偷懒用的vector,结果一直爆栈.把G++改成C++就过了.. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <se

HDU 2586 + HDU 4912 最近公共祖先

先给个LCA模板 HDU 1330(LCA模板) #include <cstdio> #include <cstring> #define N 40005 struct Edge{ int x,y,d,ne; }; Edge e[N*2],e2[N*2]; int be[N],be2[N],all,all2,n,m; bool vis[N]; int fa[N]; int ancestor[N][3]; int dis[N]; void add(int x, int y, int

LCA(最近公共祖先)--tarjan离线算法 hdu 2586

HDU 2586 How far away ? Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 11320    Accepted Submission(s): 4119 Problem Description There are n houses in the village and some bidirectional roads c

最近公共祖先(lca) hdu 2586

hdu 2586 How far away ? 题目大意:给定n-1条边构成一棵树,无向的:和m个询问,对于每一个询问按顺序回答. 结题思路:lca算法算出最近公共祖先,然后dis[u]+dis[v]-2*dis[father](father是u,v的最近公共祖先),小trick是在构造询问树的时候把权值设成询问对应的输入顺序 #include <iostream> #include <cstdio> #include <cstring> #include <al