zoukankan      html  css  js  c++  java
  • [noip模拟]祖孙询问<LCA>

    【问题描述】

     

        已知一棵n个节点的有根树。有m个询问。每个询问给出了一对节点的编号x和y,询问x与y的祖孙关系。

    【输入格式】

        输入第一行包括一个整数n表示节点个数。

        接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。

        第n+2行是一个整数m表示询问个数。

        接下来m行,每行两个正整数x和y。

    【输出格式】

        对于每一个询问,输出1:如果x是y的祖先,输出2:如果y是x的祖先,否则输出0。

    【样例输入】

    10

    234 -1

    12 234

    13 234

    14 234

    15 234

    16 234

    17 234

    18 234

    19 234

    233 19

    5

    234 233

    233 12

    233 13

    233 15

    233 19

    【样例输出】

    1

    0

    0

    0

    2

    【数据规模】

        对于30%的数据,n,m≤1000。

        对于100%的.据,n,m≤40000,每个节点的编号都不超过40000。

     

     

    这是去年我们考的一套题,现在回过头来看,其实不难啊,谁知道当年还做的要死要活的

    这题就是一个裸的LCA,毕竟题目都这样说了

    我用了tarjan,因为个人来说我的tarjan打的要差一些,但是打了这题后,我对tarjan求LCA的理解要正常的许多了

    裸的tarjan,额外处理就是储存一个对每一个询问边的最近公共祖先,但是我们建立询问边是建立了两条,所以要注意在储存答案时要合并起来

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #include<iostream>
     5 #include<cstdlib>
     6 #include<queue>
     7 #include<cmath>
     8 #define maxn 40005
     9 using namespace std;
    10 
    11 struct node{
    12     int u,v,nxt;
    13 }e[maxn*4],p[maxn*4];
    14 
    15 int n,m,dfn[maxn],fa[maxn],belong[maxn],root,maxid;
    16 int head[maxn],heap[maxn],vis[maxn*4],visid[maxn];
    17 int ord[maxn*4];
    18 
    19 int tot;
    20 void adde(int u,int v){e[tot]=(node){u,v,head[u]};head[u]=tot++;}
    21 
    22 int tpt;
    23 void addp(int u,int v,int pos){p[tpt]=(node){u,v,heap[u]};
    24 ord[tpt]=pos;heap[u]=tpt++;
    25 }
    26 
    27 int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]);}
    28 
    29 int num;
    30 void tarjan(int u,int from){
    31     dfn[u]=++num;
    32     for(int i=head[u];i!=-1;i=e[i].nxt ){
    33         int v=e[i].v;
    34         if(!dfn[v]){tarjan(v,u);fa[v]=u;visid[v]=1;}
    35     }
    36     for(int i=heap[u];i!=-1;i=p[i].nxt){
    37         int vv=p[i].v;
    38         if(visid[vv]&&!vis[ord[i]]){vis[ord[i]]=find(vv);}
    39     }
    40 }
    41 
    42 int main(){
    43     freopen("tarjanlca.txt","r",stdin);
    44     memset(head,-1,sizeof(head));
    45     memset(heap,-1,sizeof(heap));
    46     scanf("%d",&n);
    47     for(int i=1;i<=n;i++){
    48         int u,v;scanf("%d%d",&u,&v);
    49         if(v==-1){root=u;continue;}
    50         adde(u,v);adde(v,u);maxid=max(maxid,max(u,v));
    51     }
    52     for(int i=1;i<=maxid;i++)fa[i]=i;
    53     scanf("%d",&m);
    54     for(int i=1;i<=m;i++){
    55         int u,v;scanf("%d%d",&u,&v);
    56         addp(u,v,i);addp(v,u,i);
    57     }visid[root]=1;
    58     tarjan(root,0);
    59     for(int i=1;i<=m;i++){
    60         int lca=vis[i],pos=(i-1)*2;
    61         if(lca==p[pos].u ) puts("1");
    62         else if(lca==p[pos].v )puts("2");
    63         else puts("0");
    64     }
    65 }
    View Code

    【总结】

    tarjan大法好,可惜皮不来啊

  • 相关阅读:
    Ubuntu adb devices :???????????? no permissions (verify udev rules) 解决方法
    ubuntu 关闭显示器的命令
    ubuntu android studio kvm
    ubuntu 14.04版本更改文件夹背景色为草绿色
    ubuntu 创建桌面快捷方式
    Ubuntu 如何更改用户密码
    ubuntu 14.04 返回到经典桌面方法
    ubuntu 信使(iptux) 创建桌面快捷方式
    Eclipse failed to get the required ADT version number from the sdk
    Eclipse '<>' operator is not allowed for source level below 1.7
  • 原文地址:https://www.cnblogs.com/Danzel-Aria233/p/7810704.html
Copyright © 2011-2022 走看看