• Tarjan LCA


    GeneralLiu一篇博客<<<

    一个神奇的离线求lca方式    而且看到dfs和并查集就感觉特别亲切

    本方式使用链式前向星处理输入的树,并设置一个que[]来表示深搜的时候有没有访问过该点

    对于给定的根节点,对它进行如下处理:
    1:依次搜索和它相连的子节点,即深搜它的所有子树

    2:遍历所有与它相关的节点,即题目要问的xx与它的最近公共祖先

        如果xx已经访问过,那么它与xx的最近公共祖先即为find(xx)

        如果xx还未访问,则不做任何处理

    3:在回溯的时候将它和它的子节点合并

    看是不是很棒

    luogu有一道lca模板题可以练习这个

     放代码

      1 #include<iostream>
      2 #include<cstdlib>
      3 #include<cstdio>
      4 #include<cctype>
      5 
      6 long long read(){
      7     long long num=0,f=1;
      8     char ch=getchar();
      9     while(!isdigit(ch)){
     10         if(ch=='-')    f=-1;
     11         ch=getchar();
     12     }
     13     while(isdigit(ch)){
     14         num=num*10+ch-'0';
     15         ch=getchar();
     16     }
     17     return num*f;
     18 }
     19 
     20 
     21 
     22 using namespace std;
     23 int father[500010];
     24 int head  [500010];
     25 int qhead [500010];
     26 int que   [500010];
     27 
     28 struct Edge{
     29     int next,to;
     30 }edge[1000010];
     31 
     32 struct qEdge{
     33     int next,to,ans;
     34     qEdge(){ans=0;}
     35 }q[1000010];
     36 
     37 int cnt;
     38 void add(int x,int y){
     39     cnt++;
     40     edge[cnt].to=y;
     41     edge[cnt].next=head[x];
     42     head[x]=cnt;
     43 }
     44 
     45 void qadd(int x,int y,int k){
     46     q[k].to=y;
     47     q[k].next=qhead[x];
     48     qhead[x]=k;
     49 }
     50 
     51 int find(int x){
     52     if(father[x]!=x)    father[x]=find(father[x]);
     53     return father[x];
     54 }
     55 
     56 void unionn(int x,int y){
     57     x=find(x);y=find(y);
     58     father[y]=x;
     59 }
     60 
     61 void tarjan(int x){
     62     que[x]=1;
     63     for(int i=head[x];i;i=edge[i].next){
     64         int to=edge[i].to;
     65         if(!que[to]){
     66             tarjan(to);
     67             unionn(x,to);
     68         }
     69     }
     70     for(int i=qhead[x];i;i=q[i].next){
     71         int to=q[i].to;
     72         if(que[to]==2){
     73             q[i].ans=find(to);
     74             if(i%2)    q[i+1].ans=q[i].ans;
     75             else     q[i-1].ans=q[i].ans;
     76         }
     77     }
     78     que[x]=2;
     79 }
     80 
     81 int main(){
     82     int n=read(),m=read(),s=read();
     83     for(int i=1;i<n;++i){
     84         int x=read(),y=read();
     85         add(x,y);
     86         add(y,x);
     87         father[i]=i;
     88     }
     89     father[n]=n;
     90     for(int i=1;i<=m;++i){
     91         int x=read(),y=read();
     92         qadd(x,y,i*2-1);
     93         qadd(y,x,i*2);
     94     }
     95     tarjan(s);
     96     for(int i=1;i<=n;++i){
     97         printf("%d
    ",q[i*2].ans);
     98     }
     99     return 0;
    100 }
    对了快%%%%%%GeneralLiu
  • 相关阅读:
    如何选择硅谷的IT公司
    NSDateFormatter设定日期格式
    内存映射文件
    double 转 int 的精度损失问题
    #ifndef #define 的用法
    How to improve the performance of MB5B
    Vendor Evaluation Questionair弹出空白页
    接受报价后创建合同,却无法弹出相应的合同类型
    SRM税务代码的决定逻辑
    How to improve the performance of MB51
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/6823999.html
Copyright © 2020-2023  润新知