zoukankan      html  css  js  c++  java
  • zoj 3195(LCA加强版)

    传送门:Problem 3195

    https://www.cnblogs.com/violet-acmer/p/9686774.html

    题意:

      给一个无根树,有q个询问,每个询问3个点(a,b,c),问将这3个点连起来,距离最短是多少。

    题解:

      我的思路:

        (1)分别求出Lca(a,b),Lca(a,c),Lca(b,c);

        (2)找到三个Lca( )中深度最深的那个节点(此处假设Lca(a,b)深度最深),设变量 res = dist[a]+dist[b]-2*dist[Lca(a,b)];

        (3)求出Lca(a,b)与c的最近公共祖先,res += dist[c]+dist[Lca(a,b)]-2*dist[Lca(a,b,c)];

      参考大佬题解思路:

        分别求LCA(a,b),LCA(a,c),LCA(b,c),和对应的距离,然后3个距离相加再除以2就是这个询问的结果。

    AC代码:

      晚上看了LCA的RMQ算法的一个题,改了一晚上,貌似理解了,太累了,明天再把这个代码的细节写一下.............

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<vector>
      4 #include<cstring>
      5 using namespace std;
      6 #define pb push_back
      7 #define ll long long
      8 #define mem(a,b) (memset(a,b,sizeof a))
      9 const int maxn=5e4+50;
     10 
     11 struct Node
     12 {
     13     int to;
     14     int weight;
     15     Node(int to,int weight):to(to),weight(weight){}
     16 };
     17 vector<Node >edge[maxn];
     18 int n,q;
     19 int fa[20][maxn];
     20 int dist[maxn];
     21 int depth[maxn];
     22 void addEdge(int u,int v,int w)
     23 {
     24     edge[u].pb(Node(v,w));
     25     edge[v].pb(Node(u,w));
     26 }
     27 void Init()
     28 {
     29     for(int i=0;i < n;++i)
     30         edge[i].clear();
     31 }
     32 void Dfs(int u,int f,int d,int l)
     33 {
     34     fa[0][u]=f;
     35     dist[u]=l;
     36     depth[u]=d;
     37     for(int i=0;i < edge[u].size();++i)
     38     {
     39         int to=edge[u][i].to;
     40         int w=edge[u][i].weight;
     41         if(to != f)
     42             Dfs(to,u,d+1,l+w);
     43     }
     44 }
     45 void Pretreat()
     46 {
     47     Dfs(0,-1,0,0);
     48     for(int k=0;k+1 < 20;++k)
     49         for(int u=0;u < n;++u)
     50             if(fa[k][u] == -1)
     51                 fa[k+1][u]=-1;
     52             else
     53                 fa[k+1][u]=fa[k][fa[k][u]];
     54 }
     55 int Lca(int u,int v)
     56 {
     57     if(depth[u] > depth[v])
     58         swap(u,v);
     59     int k;
     60     for(k=0;(1<<k) <= depth[v];++k);
     61     k--;
     62     for(int i=k;i >= 0;--i)
     63         if((depth[v]-(1<<i)) >= depth[u])
     64             v=fa[i][v];
     65     if(u == v)
     66         return v;
     67     for(int i=k;i >= 0;--i)
     68         if(fa[i][v] != -1 && fa[i][v] != fa[i][u])
     69         {
     70             v=fa[i][v];
     71             u=fa[i][u];
     72         }
     73     return fa[0][v];
     74 }
     75 int main()
     76 {
     77     bool flag=false;
     78     while(~scanf("%d",&n))
     79     {
     80         Init();
     81         if(flag)
     82             printf("
    ");
     83         flag=true;
     84         for(int i=1;i < n;++i)
     85         {
     86             int u,v,w;
     87             scanf("%d%d%d",&u,&v,&w);
     88             addEdge(u,v,w);
     89         }
     90         Pretreat();
     91         scanf("%d",&q);
     92         for(int i=1;i <= q;++i)
     93         {
     94             int a,b,c;
     95             scanf("%d%d%d",&a,&b,&c);
     96             int res;
     97             int lcaAB=Lca(a,b);
     98             int lcaAC=Lca(a,c);
     99             int lcaBC=Lca(b,c);
    100             if(depth[lcaAB] > depth[min(lcaAC,lcaBC)])
    101             {
    102                 res=dist[a]-dist[lcaAB]+dist[b]-dist[lcaAB];
    103                 res += dist[lcaAB]-dist[Lca(lcaAB,c)]+dist[c]-dist[Lca(lcaAB,c)];
    104             }
    105             else if(depth[lcaAC] > depth[min(lcaAB,lcaBC)])
    106             {
    107                 res=dist[a]-dist[lcaAC]+dist[c]-dist[lcaAC];
    108                 res += dist[lcaAC]-dist[Lca(lcaAC,b)]+dist[b]-dist[Lca(lcaAC,b)];
    109             }
    110             else
    111             {
    112                 res=dist[b]-dist[lcaBC]+dist[c]-dist[lcaBC];
    113                 res += dist[lcaBC]-dist[Lca(lcaBC,a)]+dist[a]-dist[Lca(lcaBC,a)];
    114             }
    115             printf("%d
    ",res);
    116         }
    117     }
    118     return 0;
    119 }
    基于二分的LCA
  • 相关阅读:
    打印杨辉三角形
    Java中的基本数据类型
    C语言网上点餐系统1.0
    C语言中常用的输入和输出函数
    ubantu忘记登录密码怎么办?(ubantu16.04)
    Linux常用服务器构建-samba(ubantu)
    Vue为文件目录设置别名
    css内容占满全屏
    Vue中引入了better-scroll后 页面上的点击事件不生效了
    javascript中获取dom元素高度和宽度的方法
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9757499.html
Copyright © 2011-2022 走看看