hdu 2586 How far away ? 倍增求LCA

倍增求LCA

LCA函数返回(u,v)两点的最近公共祖先

#include <bits/stdc++.h>
using namespace std;

const int N = 40010*2;
struct node {
    int v,val,next;
    node(){}
    node(int vv,int va,int nn):v(vv),val(va),next(nn){}
}E[N];
int n,m;
int tot,head[N],dis[N],f[N][20],dep[N];

void init() {
    tot = 0;
    memset(head,0,sizeof(head));
    memset(dis,0,sizeof(dis));
    memset(f,0,sizeof(f));
    memset(dep,0,sizeof(dep));
}

void add(int u,int v,int val) {
    E[++tot].next = head[u];
    E[tot].v = v;
    E[tot].val = val;
    head[u] = tot;
}

void addEdge(int u,int v,int val) {
    add(u,v,val);
    add(v,u,val);
}

void dfs(int x,int fa) {
    f[x][0] = fa;
    for(int i=1;f[x][i-1];i++)
        f[x][i] = f[f[x][i-1]][i-1];
    for(int i=head[x]; i; i=E[i].next) {
        int v = E[i].v;
        if(v != fa) {
            dis[v] = dis[x] + E[i].val;
            dep[v] = dep[x] + 1;
            dfs(v,x);
        }
    }
}

int lca(int u,int v) {
    if(dep[u] < dep[v]) swap(u,v);
    //int ans = dep[u] - dep[v];
    for(int i=19;i>=0;i--)
        if(dep[u]-(1<<i)>=dep[v])
            u = f[u][i];
    for(int i=19;i>=0;i--) {
        if(f[u][i]!=f[v][i])
            u=f[u][i],v=f[v][i];//ans+=(2<<i);
    }
    //if(u!=v) ans+=2;
    //return ans;
    if(u!=v) return f[u][0];
    else return u;
}

int main () {
    //freopen("in.txt","r",stdin);
    int T; scanf("%d",&T);
    while (T--) {
        init();
        scanf("%d %d",&n, &m);
        for(int i=1;i<=n-1;i++) {
            int u,v,val;
            scanf("%d %d %d",&u,&v,&val);
            addEdge(u,v,val);
        }
        dfs(1,0);
        // cout <<"yes" <<endl;
        while(m--) {
            int u,v; scanf("%d %d",&u,&v);
            int  t = lca(u,v);
            printf("%d\n",dis[u]+dis[v]-2*dis[t]);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Draymonder/p/9617303.html

时间: 2024-09-30 05:11:10

hdu 2586 How far away ? 倍增求LCA的相关文章

HDU 4081 Qin Shi Huang&#39;s National Road System 最小生成树+倍增求LCA

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081 Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5428    Accepted Submission(s): 1902 Problem Description

【LCA】倍增求LCA

题目描述 如题,给定一棵有根多叉树,请求出指定两个点直接最近的公共祖先. 输入输出格式 输入格式: 第一行包含三个正整数N.M.S,分别表示树的结点个数.询问的个数和树根结点的序号. 接下来N-1行每行包含两个正整数x.y,表示x结点和y结点之间有一条直接连接的边(数据保证可以构成树). 接下来M行每行包含两个正整数a.b,表示询问a结点和b结点的最近公共祖先. 输出格式: 输出包含M行,每行包含一个正整数,依次为每一个询问的结果. 输入输出样例 输入样例#1: 复制 5 5 4 3 1 2 4

POJ 1986:Distance Queries(倍增求LCA)

http://poj.org/problem?id=1986 题意:给出一棵n个点m条边的树,还有q个询问,求树上两点的距离. 思路:这次学了一下倍增算法求LCA.模板. dp[i][j]代表第i个点的第2^j个祖先是哪个点,dp[i][0] = i的第一个祖先 = fa[i].转移方程:dp[i][j] = dp[dp[i][j-1][j-1]. 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm&g

tarjan,树剖,倍增求lca

1.tarjan求lca Tarjan(u)//marge和find为并查集合并函数和查找函数 { for each(u,v) //访问所有u子节点v { Tarjan(v); //继续往下遍历 marge(u,v); //合并v到u上 标记v被访问过; } for each(u,e) //访问所有和u有询问关系的e { 如果e被访问过; u,e的最近公共祖先为find(e); } } 2.倍增lca(在线) #include<bits/stdc++.h> using namespace st

【OI】倍增求LCA

╭(′▽`)╯ 总之,我们都知道lca是啥,不需要任何基础也能想出来怎么用最暴力的方法求LCA,也就是深度深的点先跳到深度浅的点的同一深度,然后一起向上一步步跳.这样显然太慢了! 所以我们要用倍增,倍增比较屌,直接2^k速度往上跳,而且复杂度和树剖lca差不多,那么步骤分为两步 1.让两个点到同一深度 2.到了同一深度同步往上跳 反正我一开始看的时候一直在想,万一跳过了怎么办?哈哈哈,所以说我们有办法嘛: 定义deepv为v点的深度,设两个要求lca的点分别为a,b,且deepa >= deep

(贪心+倍增求LCA) hdu 4912

Paths on the tree Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1097    Accepted Submission(s): 366 Problem Description bobo has a tree, whose vertices are conveniently labeled by 1,2,…,n. T

HDU 2586 How far away ? (离线LCA Tarjan算法模板)

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

HDU 2586 How far away ?(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

HDU 2586 How far away ?(LCA在线算法实现)

http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵树,求出树上任意两点之间的距离. 思路: 这道题可以利用LCA来做,记录好每个点距离根结点的距离,然后只要计算出两点的LCA,这样一来答案就是distance[u]+distance[v]-2distance[LCA]. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #includ