zoukankan      html  css  js  c++  java
  • [Luogu] 模板题-最近公共祖先

    树链剖分版本:

     1 #include<cstdio>
     2 #include<iostream>
     3 #define maxn 1000000
     4 using namespace std;
     5 
     6 int siz[maxn],fa[maxn],depth[maxn],son[maxn],top[maxn],n,m,s;
     7 
     8 struct edge{
     9     int from,v;
    10 }e[maxn];
    11 int tot,first[maxn];
    12 void insert(int u,int v){
    13     tot++; e[tot].from = first[u]; e[tot].v = v; first[u] = tot;
    14 }
    15 
    16 void dfs(int now){
    17     siz[now] = 1;
    18     for(int i = first[now];i;i = e[i].from){
    19         int v = e[i].v;
    20         if(v != fa[now]){
    21             fa[v] = now;
    22             depth[v] = depth[now]+1;
    23             dfs(v);
    24             siz[now] += siz[v];
    25             if(!son[now] || siz[v] > siz[son[now]])
    26                 son[now] = v;
    27         }
    28     }
    29 }
    30 
    31 void dfs2(int now,int t){
    32     top[now] = t;
    33     if(!son[now]) return;
    34     dfs2(son[now],t);
    35     for(int i = first[now];i;i = e[i].from){
    36         int v = e[i].v;
    37         if(v != fa[now] && v != son[now])
    38             dfs2(v,v);
    39     }
    40 }
    41 
    42 int LCA(int u,int v){
    43     if(depth[top[u]] < depth[top[v]]) swap(u,v);
    44     while(top[u] != top[v]){
    45         u = fa[top[u]];
    46         if(depth[top[u]] < depth[top[v]]) swap(u,v);
    47     }if(depth[u] < depth[v]) swap(u,v);
    48     return v;
    49 }
    50 
    51 int main(){
    52     scanf("%d%d%d",&n,&m,&s);
    53     
    54     for(int i = 1;i < n;i++){
    55         int x,y; scanf("%d%d",&x,&y);
    56         insert(x,y); insert(y,x);
    57     }depth[s] = 1; dfs(s); dfs2(s,s);
    58     
    59     while(m--){
    60         int u,v;
    61         scanf("%d%d",&u,&v);
    62         printf("%d
    ",LCA(u,v));
    63     }
    64     
    65     return 0;
    66 }
    链剖据说log n?

    Tarjan版本:

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 #define maxn 500005
     5 using namespace std;
     6 
     7 struct edge{
     8     int from,u,v,ans,order;
     9 }e[maxn*2+5],e1[maxn*2+5];
    10 
    11 int pre[maxn];
    12 int find(int x){
    13     if(!pre[x]) return x;
    14     else{
    15         pre[x] = find(pre[x]);
    16         return pre[x];
    17     }
    18 }
    19 
    20 bool book[maxn];
    21 int tot,tot1,first1[maxn],first[maxn],n,m,s;
    22 void insert(int u,int v){
    23     tot++;
    24     e[tot].from = first[u];
    25     e[tot].v = v;
    26     e[tot].u = u;
    27     first[u] = tot;
    28 }
    29 
    30 void insert1(int u,int v,int i){
    31     tot1++;
    32     e1[tot1].order = i;
    33     e1[tot1].from = first1[u];
    34     e1[tot1].u = u;
    35     e1[tot1].v = v;
    36     first1[u] = tot1;
    37 }
    38 
    39 bool cmp(const edge &a,const edge &b){
    40     return a.order < b.order;
    41 }
    42 
    43 void Tarjan(int now,int father){
    44     for(int i = first[now];i;i = e[i].from){
    45         int v = e[i].v;
    46         if(v == father) continue;
    47         Tarjan(v,now);
    48         pre[find(v)] = find(now);
    49         book[v] = true;
    50     }
    51     
    52     for(int i = first1[now];i;i = e1[i].from){
    53         int v = e1[i].v;
    54         if(v == father) continue;
    55         if(book[v]){
    56             e1[i].ans = find(v);
    57         }
    58     }
    59 }
    60 
    61 int main(){
    62     scanf("%d%d%d",&n,&m,&s);
    63     for(int i = 1;i < n;i++){
    64         int a,b;
    65         scanf("%d%d",&a,&b);
    66         insert(a,b);
    67         insert(b,a);
    68     }
    69     
    70     for(int i = 1;i <= m;i++){
    71         int a,b;
    72         scanf("%d%d",&a,&b);
    73         insert1(a,b,i);
    74         insert1(b,a,i);
    75     }
    76     
    77     Tarjan(s,-1);
    78     
    79     sort(e1+1,e1+1+tot1,cmp);
    80     
    81     for(int i = 1;i <= tot1;i+=2){
    82         if(!e1[i].ans) printf("%d
    ",e1[i+1].ans);
    83         else printf("%d
    ",e1[i].ans);
    84     }
    85     
    86     return 0;
    87 }
    用邻接表顺便储存询问
    转载请注明出处 -- 如有意见欢迎评论
  • 相关阅读:
    给xml某个节点赋值
    把datatable的某些数据提取出来放在另一个表中
    投资技巧:抛股票有技巧 常用方法介绍
    jquery的实用技巧,非常实用
    我觉得需要关注和跟进的一些.net技术
    公司网站的架构
    uboot移植经历
    ARM处理器中CP15协处理器的寄存器
    uboot 学习 Makefile分析
    uboot移植
  • 原文地址:https://www.cnblogs.com/Chorolop/p/7471686.html
Copyright © 2011-2022 走看看