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 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"? Usually it hard to
answer. But luckily int this village the answer is always unique, since the roads are built in the way that there is a unique simple path("simple" means you can‘t visit a place twice) between every two houses. Yout task is to answer all these curious people.

Input

First line is a single integer T(T<=10), indicating the number of test cases.

For each test case,in the first line there are two numbers n(2<=n<=40000) and m (1<=m<=200),the number of houses and the number of queries. The following n-1 lines each consisting three numbers i,j,k, separated bu a single space, meaning that there is a road
connecting house i and house j,with length k(0<k<=40000).The houses are labeled from 1 to n.

Next m lines each has distinct integers i and j, you areato answer the distance between house i and house j.

Output

For each test case,output m lines. Each line represents the answer of the query. Output a bland line after each test case.

Sample Input

2
3 2
1 2 10
3 1 15
1 2
2 3

2 2
1 2 100
1 2
2 1

Sample Output

10
25
100
100

Source

ECJTU 2009 Spring Contest

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

题目大意:给一个带权树,m次询问,求两点之间的距离

题目分析:裸的LCA问题,采用离线的Tarjan算法

#include <cstdio>
#include <cstring>
int const MAX = 40005;

struct Edge
{
    int id, val; //当前边序号,边权
    int next;  //下一条
}e[2 * MAX];

int n, m, cnt;
//x, y表示询问的起点和终点,z是x和y的LCA
int x[MAX], y[MAX], z[MAX];
//fa存祖先,dist存到根的距离,pre存父亲
int fa[MAX], dist[MAX], pre[MAX];
bool vis[MAX];

void AddEdge(int u, int v, int w)
{
    e[cnt].id = u;
    e[cnt].val = w;
    e[cnt].next = pre[v];
    pre[v] = cnt++;

    e[cnt].id = v;
    e[cnt].val = w;
    e[cnt].next = pre[u];
    pre[u] = cnt++;
}

int Find(int x)
{
    return x == fa[x] ? x : fa[x] = Find(fa[x]);
}

void tarjan(int k)
{
    vis[k] = true;
    fa[k] = k;
    for(int i = 1; i <= m; i++)
    {
        if(x[i] == k && vis[y[i]])
            z[i] = Find(y[i]);
        if(y[i] == k && vis[x[i]])
            z[i] = Find(x[i]);
    }
    for(int i = pre[k]; i != -1; i = e[i].next)
    {
        if(!vis[e[i].id])
        {
            dist[e[i].id] = dist[k] + e[i].val;
            tarjan(e[i].id);
            fa[e[i].id] = k;
        }
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int u, v, w;
        scanf("%d %d", &n, &m);
        cnt = 0;
        memset(pre, -1, sizeof(pre));
        for(int i = 1; i < n; i++)
        {
            scanf("%d %d %d", &u, &v, &w);
            AddEdge(u, v, w);
        }
        for(int i = 1; i <= n; i++)
            x[i] = y[i] = z[i] = 0;
        for(int i = 1; i <= m; i++)
        {
            scanf("%d %d", &u, &v);
            x[i] = u;
            y[i] = v;
        }
        memset(vis, false, sizeof(vis));
        dist[1] = 0;
        tarjan(1);
        for(int i = 1; i <= m; i++)
            printf("%d\n",dist[x[i]] + dist[y[i]] - 2 * dist[z[i]]);
    }
}
时间: 2024-10-29 10:45:44

HDU 2586 How far away ? (离线LCA Tarjan算法模板)的相关文章

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): 10312    Accepted Submission(s): 3743 Problem Description There are n houses in the village and some bidirectional roads connecting

hihoCoder #1067 : 最近公共祖先&#183;二 [ 离线LCA tarjan ]

传送门: #1067 : 最近公共祖先·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上上回说到,小Hi和小Ho用非常拙劣——或者说粗糙的手段山寨出了一个神奇的网站,这个网站可以计算出某两个人的所有共同祖先中辈分最低的一个是谁.远在美国的他们利用了一些奇妙的技术获得了国内许多人的相关信息,并且搭建了一个小小的网站来应付来自四面八方的请求. 但正如我们所能想象到的……这样一个简单的算法并不能支撑住非常大的访问量,所以摆在小Hi和小Ho面前的无非两种选择: 其一是

最近公共祖先LCA(Tarjan算法)的思考和算法实现——转载自Vendetta Blogs

最近公共祖先LCA(Tarjan算法)的思考和算法实现 LCA 最近公共祖先 Tarjan(离线)算法的基本思路及其算法实现 小广告:METO CODE 安溪一中信息学在线评测系统(OJ) //由于这是第一篇博客..有点瑕疵...比如我把false写成了flase...看的时候注意一下! //还有...这篇字比较多 比较杂....毕竟是第一次嘛 将就将就 后面会重新改!!! 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先

tarjan算法模板

var {left表示点 root 没离开栈 vis表示点 root 有没有被访问过} i,n,m,now,time,color,top:longint; v:array[0..10001] of record start:longint;end; e:array[0..100001] of record y,next:longint;end; dfn,low,stack,encolor:array[0..10001] of longint; vis,left:array[0..10001] o

HDU 2544 最短路(我的dijkstra算法模板、SPAFA算法模板)

思路:这道题是基础的最短路径算法,可以拿来试一下自己对3种方法的理解 dijkstra主要是从第一个点开始枚举,每次枚举出当当前最小的路径,然后再以那最小的路径点为起点,求出它到其它未标记点的最短距离 bellman-ford 算法则是假设有向网中有n 个顶点.且不存在负权值回路,从顶点v1 和到顶点v2 如果存在最短路径,则此路径最多有n-1 条边.这是因为如果路径上的边数超过了n-1 条时,必然会重复经过一个顶点,形成回路:而如果这个回路的权值总和为非负时,完全可以去掉这个回路,使得v1到v

【HDU 2586 How far away?】LCA问题 Tarjan算法

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2586 题意:给出一棵n个节点的无根树,每条边有各自的权值.给出m个查询,对于每条查询返回节点u到v的最短路径的权值和,按查询顺序输出结果. 数据范围:n [2, 40000], m[1, 200] 思路:Tarjan算法:dfs遍历每个点,每遍历完 r 的一个孩子 c, 把 c 并入以 r 为祖先的集合,并处理 c 的所有查询 q:若qi的目标节点 v 已被遍历到,那么一定有lca(c, v) =

HDU 2586 How far away ? (LCA,Tarjan, spfa)

题意:给定N个节点一棵树,现在要求询问任意两点之间的简单路径的距离,其实也就是最短路径距离. 析:用LCA问题的Tarjan算法,利用并查集的优越性,产生把所有的点都储存下来,然后把所有的询问也储存下来,然后从树根开始搜索这棵树, 在搜索子树的时候,把并查集的父结点不断更新,在搜索时计算答案,d[i] 表示从根结点到 i 结点的距离,然后分别计算到两个结点的距离, 再减去2倍的根结点到他们公共最近的结点距离,就OK了.不过这个题有个坑人的地方,不用输出那个空行,否则就是PE. 因为这个题询问比较

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

我对最近公共祖先LCA(Tarjan算法)的理解

LCA 最近公共祖先 Tarjan(离线)算法的基本思路及我个人理解 首先是最近公共祖先的概念(什么是最近公共祖先?): 在一棵没有环的树上,每个节点肯定有其父亲节点和祖先节点,而最近公共祖先,就是两个节点在这棵树上深度最大的公共的祖先节点. 换句话说,就是两个点在这棵树上距离最近的公共祖先节点. 所以LCA主要是用来处理当两个点仅有唯一一条确定的最短路径时的路径. 有人可能会问:那他本身或者其父亲节点是否可以作为祖先节点呢? 答案是肯定的,很简单,按照人的亲戚观念来说,你的父亲也是你的祖先,而