zoukankan      html  css  js  c++  java
  • HDU 2586 How far away ? << LCA+tarjin求树上任两点最短距离裸题

    题意

    给你一棵树和每条边的权值,m次询问,求任两点间距离,LCA+tarjin裸题。

    思路

    能用的算法大概也很多吧,但是就为了练一手LCA+tarjin我就来做这题了,够裸了,还能验板子233。

    这个算法主要是用到了并查集,找LCA,在找到询问对的时候存下LCA。然后最后利用公式结合tarjin得来的距离和LCA直接得出答案。

    所以说此处我们进行遍历的目的有两个——1.找到目标点对的LCA,2.找到所有点距离初始点的距离。最后的答案是通过以上我们得到的信息算出来的。

    该题详情请见代码。

    代码

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 const int N=4e4+5;
     4 typedef pair<int,int> PII;
     5 struct edge{
     6     int to,len;
     7 };
     8 struct askedge{
     9     int from,to,lca;
    10 }ae[300];//询问对
    11 int n,m;
    12 vector<edge> G[N];//邻接表
    13 vector<PII> pp[N];//存储每个点相对的询问点
    14 int dist[N];//距离
    15 int fa[N];//并查集
    16 int Find(int x)
    17 {
    18     if(x==fa[x]) return x;
    19     else return fa[x]=Find(fa[x]);
    20 }
    21 void Union(int x,int y)
    22 {
    23     x=Find(x);y=Find(y);
    24     if(x!=y) fa[y]=x;
    25 }
    26 void dfs(int now)
    27 {
    28     fa[now]=now;//初始化,分离成init()函数也没问题
    29     for(int i=0;i<pp[now].size();i++)//看当前这个点有没有它的点对已经被搜索到
    30     {
    31         PII &v=pp[now][i];
    32         if(dist[v.first]!=-1){
    33             ae[v.second].lca=fa[v.first];//如果存在,他们的lca就是当前点对象的爸爸
    34         }
    35     }
    36     for(int i=0;i<G[now].size();i++)//遍历搜索
    37     {
    38         edge &v=G[now][i];
    39         if(dist[v.to]==-1)
    40         {
    41             dist[v.to]=dist[now]+v.len;
    42             dfs(v.to);
    43             Union(now,v.to);//回溯时合并
    44         }
    45     }
    46 }
    47 int main()
    48 {
    49     int T;
    50     scanf("%d",&T);
    51     while(T--)
    52     {
    53         scanf("%d%d",&n,&m);
    54         for(int i=0;i<=n;i++)//初始化
    55         {
    56             pp[i].clear();
    57             G[i].clear();
    58         }
    59         for(int i=0;i<=m;i++)
    60             pp[i].clear();
    61         for(int i=0,u,v,len;i<n-1;i++)//读入图
    62         {
    63             scanf("%d%d%d",&u,&v,&len);
    64             G[u].push_back(edge {v,len});
    65             G[v].push_back(edge {u,len});
    66         }
    67         for(int i=1;i<=m;i++)//读入询问
    68         {
    69             int u,v;
    70             scanf("%d%d",&u,&v);
    71             pp[u].push_back(make_pair(v,i));
    72             pp[v].push_back(make_pair(u,i));
    73             ae[i]={u,v,-1};
    74         }
    75         memset(dist,-1,sizeof(dist));
    76         dist[1]=0;
    77         dfs(1);//开始tarjin
    78         for(int i=1;i<=m;i++)//对每次询问输出答案
    79         {
    80             askedge &u=ae[i];
    81             printf("%d
    ",dist[u.from]+dist[u.to]-2*dist[u.lca]);//公式
    82         }
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    函数特化
    模板函数总结
    学习代码1
    宏指令
    #define宏作用
    oracle 重要函数
    JMeter 系列之—-01 使用
    Selenium系列之--03 常见元素操作总结
    【转】TestNG常用注解
    CMMI 2,3,4,5级涉及的过程域(PA)介绍
  • 原文地址:https://www.cnblogs.com/computer-luo/p/9622227.html
Copyright © 2011-2022 走看看