zoukankan      html  css  js  c++  java
  • HDU 2586 ( LCA/tarjan算法模板)

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

    题意:n个村庄构成一棵无根树,q次询问,求任意两个村庄之间的最短距离

    思路:求出两个村庄的LCA,dis[ i ] 表示结点 i 到树根的距离,那么任意两点u,v的最短距离就是dis[ u ]  - dis [LCA] + dis [ v ] - dis[ LCA ]。代码是用tarjan做的,算是模板,记录一下。 

    AC代码:

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<vector>
     6 #include<queue> 
     7 using namespace std;
     8 const int maxn = 40005;
     9 struct node{//询问的结点x,y 
    10     int x,y;
    11     int lca;
    12 }query[maxn];
    13 struct e{//建边 
    14     int to;
    15     int val;
    16 };
    17 int dis[maxn];
    18 vector<e> G[maxn];
    19 vector<int> Q[maxn];
    20 bool vis[maxn];
    21 int N;
    22 int fa[maxn];
    23 void init(){//初始化父亲结点 
    24     for(int i = 0;i<maxn;i++) fa[i] = i;
    25 }
    26 int find(int x){//并查集find函数 
    27     if(x == fa[x]) return x;
    28     return fa[x] = find(fa[x]);
    29 }
    30 void tarjan(int cur){
    31     vis[cur] = true;//标记cur已访问过 
    32     for(auto q:Q[cur]){//遍历包含cur结点的询问 
    33         if(query[q].x == cur){ 
    34             if(vis[query[q].y]) {//若x == cur且y已经被访问过,搜y的祖先,就是其LCA 
    35                 query[q].lca = find(query[q].y);
    36             }
    37         }
    38         else{
    39             if(vis[query[q].x]){//若y == cur且x已经被访问过,搜x的祖先,就是其LCA 
    40                 query[q].lca = find(query[q].x);
    41             }
    42         }
    43     }
    44     for(auto e:G[cur]){//遍历cur结点的儿子结点 
    45         int v = e.to , len = e.val ;
    46         if(vis[v]) continue;
    47         dis[v] = dis[cur] + len;//dis记录cur到root的距离 
    48         tarjan(v);
    49         fa[v] = cur; //设置cur结点子节点的父亲为cur 
    50     }
    51 }
    52 int main(){
    53     int t;scanf("%d",&t);
    54     while(t--){
    55         scanf("%d",&N);
    56         int q;
    57         memset(vis,0,sizeof(vis));
    58         init();
    59         for(int i = 0;i<maxn;i++) {//初始化 
    60             Q[i].clear() ,G[i].clear() ;
    61             query[i].lca = 0,query[i].x = 0,query[i].y = 0;
    62         }
    63         scanf("%d",&q);
    64         for(int i = 1;i<=N-1;i++){
    65             int u,v,k;
    66             scanf("%d%d%d",&u,&v,&k);
    67             G[u].push_back({v,k}); //建图 
    68             G[v].push_back({u,k}); 
    69         }
    70         for(int i = 1;i<=q;i++){
    71             scanf("%d%d",&query[i].x ,&query[i].y );
    72             Q[query[i].x ].push_back(i);
    73             Q[query[i].y ].push_back(i);  //离线存储所有询问 ,i为标号 
    74         }
    75         tarjan(1);
    76         for(int i = 1;i<=q;i++){
    77             int LCA = query[i].lca ;
    78             int ans = dis[query[i].x ] + dis[query[i].y ] - 2*dis[LCA];//输出所有的询问 
    79             printf("%d
    ",ans);
    80         }
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    排序sort (一)
    c++实现二叉树笔记(模板实现)(三)
    树(二叉树)的建立和遍历算法(二)
    IO流之字节流
    计算机基础知识
    计算机启动过程
    2020软考报名计划表
    2020软件工程作业02
    初来乍到 20200904
    关于考研
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12203824.html
Copyright © 2011-2022 走看看