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): 11204    Accepted Submission(s): 4079

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

一个村子里有n个房子,这n个房子用n-1条路连接起来,接下了有m次询问,每次询问两个房子a,b之间的距离是多少。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <algorithm>
#include <set>
using namespace std;
typedef long long ll;
typedef unsigned long long Ull;
#define MM(a,b) memset(a,b,sizeof(a));
const double eps = 1e-10;
const int  inf =0x7f7f7f7f;
const double pi=acos(-1);
const int maxn=40000;

struct Edge{
    int to,w;
    Edge(int a,int b):to(a),w(b){};
    Edge(){};
}e[maxn+10];

struct node{
   int to,id;
};

vector<Edge> G[maxn+10];
vector<node> mp[maxn+10];
int vis[maxn+10],query[maxn+10][4],par[maxn+10],dis[maxn+10];

int findr(int u)
{
    if(par[u]!=u)
        par[u]=findr(par[u]);
    return par[u];
}

void unite(int u,int v)
{
    int ru=findr(u);
    int rv=findr(v);
    if(ru!=rv) par[rv]=ru;
}

void tarjan(int u,int val)
{
    vis[u]=1;
    dis[u]=val;

    for(int i=0;i<mp[u].size();i++)
    {
        int v=mp[u][i].to;
        int id=mp[u][i].id;
        if(vis[v])
            query[id][2]=findr(v);
    }

    for(int i=0;i<G[u].size();i++)
    {
        int v=G[u][i].to;
        if(vis[v]) continue;
        tarjan(v,val+G[u][i].w);
        unite(u,v);
    }

}

int main()
{
    int cas,n,op,u,v,w;
    scanf("%d",&cas);
    while(cas--)
    {
        scanf("%d %d",&n,&op);

        for(int i=1;i<=n;i++)
        {
            G[i].clear();
            mp[i].clear();
            vis[i]=0;
            par[i]=i;
        }

        for(int i=1;i<=n-1;i++)
        {
            scanf("%d %d %d",&u,&v,&w);
            G[u].push_back(Edge(v,w));
            G[v].push_back(Edge(u,w));
        }

        for(int i=1;i<=op;i++)
        {
            scanf("%d %d",&u,&v);
            query[i][0]=u;
            query[i][1]=v;
            mp[u].push_back((node){v,i});
            mp[v].push_back((node){u,i});
        }

        tarjan(1,0);

        for(int i=1;i<=op;i++)
        {
            int u=query[i][0];
            int v=query[i][1];
            int r=query[i][2];
            printf("%d\n",dis[u]+dis[v]-2*dis[r]);
        }
    }
    return 0;
}

分析:用的lca

1.因为有n-1条边,任意两点之间可达,那么就是一棵树;

2,假设当前是询问u和v两个点,他们的LCA是r,dis[]数组代表从根到点的距离,那么u和v两点之间的距离就是dis[u]+dis[v]-2*dis[r];所以只需要用Tarjan求一求询问的点对的LCA并且记录一下每个点到根(随便哪个点做根都可以)的距离就可以了

时间: 2024-08-14 00:49:00

HDU 2586 How far away LCA的离线算法 Tarjan的相关文章

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 How far away ?(离线Tarjan算法)

1.给定一棵树,每条边都有一定的权值,q次询问,每次询问某两点间的距离. 2.这样就可以用LCA来解,首先找到u, v 两点的lca,然后计算一下距离值就可以了. 这里的计算方法是,记下根结点到任意一点的距离dis[],这样ans = dis[u] + dis[v] - 2 * dis[lca(u, v)] 3. /* 离线算法,LCATarjan 复杂度O(n+Q); */ #include<iostream> #include<stdio.h> #include<stri

HDU 2874 LCA离线算法 tarjan算法

给出N个点,M条边,Q次询问 Q次询问每两点之间的最短距离 典型LCA 问题   Marjan算法解 #include "stdio.h" #include "string.h" struct Edge { int to,next,len; }edge[20010]; struct Ques { int to,next,index; }ques[2000010]; int head[10010],q_head[10010],f[10010],dis[10010];

LCA离线算法Tarjan详解

离线算法也就是需要先把所有查询给保存下来,最后一次输出结果. 离线算法是基于并查集实现的,首先就是初始化P[i] = i. 接下来对于每个点进行dfs: ①首先判断是否有与该点有关的查询,如果当前该点为u,与它有关的点为v,如果v已经访问过了,那么它们的LCA就是find(v).如果v还没有访问,那就不用管它. ②对该点的子节点继续dfs,需要注意的是,dfs完之后需要需要p[v]=u,将v点并到其父亲节点上. 1 void LCA(int u) 2 { 3 vis[u]=1; 4 for(in

HDU 2586 How far away ? (初学LCA)

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

LCA最近公共祖先 在线算法和离线算法 模板

原理讲解:http://dongxicheng.org/structure/lca-rmq/ 在线算法模板: /** LCA在线算法O(nlogn) 主函数调用: init(); tot=0,dir[1]=0; dfs(1,1); ST(2*n-1); int lca=LCA(u,v); */ #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> #in

【C++】最近公共祖先LCA(Tarjan离线算法)&amp;&amp; 洛谷P3379LCA模板

1.前言 首先我们介绍的算法是LCA问题中的离线算法-Tarjan算法,该算法采用DFS+并查集,再看此算法之前首先你得知道并查集(尽管我相信你如果知道这个的话肯定是知道并查集的),Tarjan算法的优点在于相对稳定,时间复杂度也比较居中,也很容易理解(个人认为). 2.思想 下面详细介绍一下Tarjan算法的思想: 1.任选一个点为根节点,从根节点开始. 2.遍历该点u所有子节点v,并标记这些子节点v已被访问过. 3.若是v还有子节点,返回2,否则下一步. 4.合并v到u上. 5.寻找与当前点

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

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