• hdu 2586 How far away ?(LCA)


    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
    解题思路:Tarjan算法求树上任意两点的最短路。
    AC代码:
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef long long LL;
     4 const int maxn=40005;
     5 const int maxv=205;
     6 int T,n,m,x,y,z,fa[maxn],dist[maxn],ans[maxv];bool vis[maxn];
     7 vector<pair<int,int> > tree[maxn],query[maxn];
     8 void init(){
     9     for(int i=1;i<=n;++i)fa[i]=i,tree[i].clear(),query[i].clear();
    10     memset(vis,false,sizeof(vis));
    11     memset(dist,0,sizeof(dist));
    12     memset(ans,0,sizeof(ans));
    13 }
    14 int query_father(int x){
    15     int per=x,tmp;
    16     while(fa[per]!=per)per=fa[per];
    17     while(x!=per){tmp=fa[x];fa[x]=per;x=tmp;}//路径压缩
    18     return x;
    19 }
    20 void unite(int x,int y){
    21     x=query_father(x),y=query_father(y);
    22     if(x!=y)fa[y]=x;
    23 }
    24 void Tarjan_LCA(int cur,int val){
    25     vis[cur]=true;///先标记为true,这样如果同一支树上前面的祖先节点已访问,但是还没有归并到集合中去相当于为其本身,所以对下面计算两个节点的最近距离是没有影响的
    26     dist[cur]=val;
    27     for(size_t i=0;i<tree[cur].size();++i){
    28         int v=tree[cur][i].first;
    29         int w=tree[cur][i].second;
    30         if(!vis[v]){
    31             Tarjan_LCA(v,val+w);///先序遍历
    32             unite(cur,v);///回退后续遍历归并集合
    33         }
    34     }
    35     for(size_t i=0;i<query[cur].size();++i){///同时扫描与cur有关的点对查询
    36         int to=query[cur][i].first;
    37         int id=query[cur][i].second;
    38         if(vis[to])ans[id]=dist[cur]+dist[to]-2*dist[query_father(to)];
    39     }
    40 }
    41 int main(){
    42     while(~scanf("%d",&T)){
    43         while(T--){
    44             scanf("%d%d",&n,&m);
    45             init();
    46             for(int i=1;i<n;++i){
    47                 scanf("%d%d%d",&x,&y,&z);
    48                 tree[x].push_back(make_pair(y,z));
    49                 tree[y].push_back(make_pair(x,z));
    50             }
    51             for(int i=1;i<=m;++i){
    52                 scanf("%d%d",&x,&y);
    53                 query[x].push_back(make_pair(y,i));
    54                 query[y].push_back(make_pair(x,i));
    55             }
    56             Tarjan_LCA(1,0);
    57             for(int i=1;i<=m;++i)printf("%d
    ",ans[i]);
    58         }
    59     }
    60     return 0;
    61 }
  • 相关阅读:
    BZOJ1786[AHOI2008]Pair配对
    [Accepted][POJ1986]Tarjan求lca
    BZOJ1265[AHOI2006]斐波卡契的兔子
    POJ2631 树最长路径
    BZOJ1406[AHOI2007密码箱]
    POJ3129计算几何水题
    [AHOI2005]SHUFFLE题解
    三分法求极值模板
    File Download Using JavaScript
    云计算IDC服务
  • 原文地址:https://www.cnblogs.com/acgoto/p/10047053.html
Copyright © 2020-2023  润新知