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\n",q[i*2].ans);
 98     }
 99     return 0;
100 }
对了快%%%%%%GeneralLiu
posted @ 2017-05-08 16:36  Konoset  阅读(520)  评论(3编辑  收藏  举报