zoukankan      html  css  js  c++  java
  • <学习笔记> 倍增 lca

    例题:codevs 2370 小机房的树

    简单来说就是给你一个n个点的树,每一条边都有边权。询问有m次,每次给出两个点,求他们之间的最小边权和。
    很容易想到用求树上前缀和和lca,先把两个点跳到高度相同的地方,再一直往上跳,直到两个点重合。因为一个点一个点的跳太慢了,所以我们倍增的跳来求lca。

    令f[i][j]表示i号点往上跳2^j步的父亲。

    则 f[i][j]=f[f[i][j-1]][j-1];

    这里有两个板子,思想都一样。

    板子一

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<cmath>
     6 using namespace std;
     7 
     8 int n,m,u,v,c,cnt;
     9 int sum[50010],deep[50010],fa[50010][30],first[50010],next[100020];
    10 struct maple{
    11     int f,t,d;
    12 }Rode[100020];
    13 
    14 void build(int f,int t,int d) //注意双向建边
    15 {
    16     Rode[++cnt]=(maple){f,t,d};
    17     next[cnt]=first[f];
    18     first[f]=cnt;
    19 }
    20 void dfs(int f,int t,int d) // dfs处理出树
    21 {
    22     deep[t]=deep[f]+1;
    23     fa[t][0]=f;
    24     sum[t]=d;
    25     for(int i=first[t];i;i=next[i])
    26        if(Rode[i].t!=f)
    27           dfs(t,Rode[i].t,d+Rode[i].d); 
    28 }
    29 void Done()  // 预处理倍增跳的fa
    30 {
    31     for(int i=1;i<=log2(n);++i) 
    32        for(int j=0;j<=n;++j)
    33           fa[j][i]=fa[fa[j][i-1]][i-1]; // j往上跳2^i等同于fa[j][i-1]往上跳i-1步,这里与st表有细微区别 
    34 }
    35 int lca(int x,int y)
    36 {
    37     if(deep[x]<deep[y]) swap(x,y); //确保x的深度大
    38     for(int i=log2(n);i>=0;--i) // 把x跳到与y深度相同的地方
    39     {
    40         if(deep[fa[x][i]]>=deep[y])
    41            x=fa[x][i];
    42     }
    43     if(x==y) return x;
    44     for(int i=log2(n);i>=0;--i)  //一起往上跳
    45        if(fa[x][i]!=fa[y][i])
    46          x=fa[x][i],y=fa[y][i];
    47     return fa[x][0];
    48 }
    49 int main()
    50 {
    51     scanf("%d",&n);
    52     for(int i=1;i<n;++i)
    53     {
    54         scanf("%d%d%d",&u,&v,&c);
    55         build(u,v,c);
    56         build(v,u,c);
    57     }
    58     dfs(0,0,0);
    59     Done();
    60     scanf("%d",&m);
    61     while(m--)
    62     {
    63         scanf("%d%d",&u,&v);
    64         printf("%d
    ",sum[u]+sum[v]-2*sum[lca(u,v)]);
    65     }
    66     return 0;
    67 }

    板子二

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cmath>
     4 #include<cstring>
     5 #include<algorithm>
     6 using namespace std;
     7 
     8 int n,u,v,c,m;
     9 int first[150010],next[150010],fa[150010][30],deep[150010],cnt;
    10 int de[60000];
    11 struct maple{
    12     int f,t,d;
    13 }rode[150010];
    14 
    15 void done(int f,int t,int v)
    16 {
    17     fa[t][0]=f;
    18     deep[t]=deep[f]+1;
    19     de[t]=de[f]+v;
    20     for(int i=1;fa[t][i-1];++i)
    21        fa[t][i]=fa[fa[t][i-1]][i-1];
    22     for(int i=first[t];i!=-1;i=next[i])
    23       if(rode[i].t!=f)
    24          done(t,rode[i].t,rode[i].d);
    25 }
    26 void build(int f,int t,int d)
    27 {
    28     rode[++cnt]=(maple){f,t,d };
    29     next[cnt]=first[f];
    30     first[f]=cnt;   
    31 }
    32 int lca(int x,int y)
    33 {
    34     if(deep[x]<deep[y]) swap(x,y);
    35     if(deep[x]>deep[y])
    36     {
    37         int l=deep[x]-deep[y];
    38         for(int i=0;i<=20;++i)
    39             if(l>>i&1) 
    40               x=fa[x][i];
    41     }          
    42     if(x==y) return x;
    43     for(int i=log2(n);i>=0;--i)
    44         if(fa[x][i]!=fa[y][i]) 
    45            x=fa[x][i],y=fa[y][i];
    46     return fa[x][0];
    47 }
    48 
    49 int main()
    50 {
    51     memset(next,-1,sizeof(next));
    52     memset(first,-1,sizeof(first));
    53     scanf("%d",&n);
    54     for(int i=1;i<n;++i)
    55     {
    56         scanf("%d%d%d",&u,&v,&c);
    57         build(u,v,c);
    58         build(v,u,c);
    59     }
    60     done(0,0,0);
    61     scanf("%d",&m);
    62     while(m--)
    63     {
    64         scanf("%d%d",&u,&v);
    65         printf("%d
    ",de[u]+de[v]-2*de[lca(u,v)]);
    66     }
    67     return 0;
    68 }
  • 相关阅读:
    android细节之禁用activity的系统的默认切换效果
    Spark1.0.0 属性配置
    Memory & MyISAM 引擎小注意! | OurMySQL
    memcached vs MySQL Memory engine table 速度比较_XMPP Jabber即时通讯开发实践_百度空间
    Mysql 官方Memcached 插件初步试用感受
    Aerospike | Aerospike Chinese
    MySQL内存表的特性与使用介绍 -- 简明现代魔法
    memory引擎的索引失效一例
    MySQL内存表(MEMORY)说明 | 一个PHP程序员的备忘录
    MySQL Memory 存储引擎浅析
  • 原文地址:https://www.cnblogs.com/maple-kingdom/p/maple-kingdom_sun.html
Copyright © 2011-2022 走看看