zoukankan      html  css  js  c++  java
  • 9018:1892: 最近公共祖先用Tarjan来做

    题目描述

    编写一个程序,查找一棵含有n个节点的树中m组两个不同节点的最近公共祖先。

    输入

    第一行两个整数n和q,为树上节点的数目和查询数。节点标号为整数 1,2,...,n。之后n-1行每一行包含一对整数,代表边——第一个整数是第二个整数的父节点。请注意,一个具有n个节点的树有n-1条边。之后q行查询,每行两个整数,表示要查询的两个节点的标号。(输入保证有且只有一棵树)

    输出

    q行,每行一个整数,为此次查询的最近公共祖先的标号

    样例输入

    5 6
    2 5
    2 3
    5 1
    1 4
    1 3
    2 3
    5 4
    1 5
    4 5
    5 4

    样例输出

    2
    2
    5
    5
    5
    5
    

    提示

    2<=n,m<=5*10^5

     代码

    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    # define INF 500010
    struct edge{int nx,t;}e[INF*3+1];
    int h[INF],q[INF],count,ans[INF],f[INF],r[INF];
    inline void ins(int*h,int x,int y){e[++count]=(edge){h[x],y};h[x]=count;}
    int gf(int k){return f[k]?f[k]=gf(f[k]):k;}
    void tj(int x){
      int i;
      for(i=q[x];i;i=e[i].nx)
        if(ans[e[i].t])ans[e[i].t]=gf(ans[e[i].t]);//最后一个ans
        else ans[e[i].t]=x;
      for(i=h[x];i;i=e[i].nx)tj(e[i].t),f[e[i].t]=x;
    }
    int main(){
      int m,n;
      scanf("%d%d",&n,&m);
      int i,x,y;
      for(i=1;i<n;++i){scanf("%d",&x);scanf("%d",&y);r[y]=1;ins(h,x,y);}//++i,怎样输入
      for(i=0;i<m;++i){scanf("%d",&x);scanf("%d",&y);ins(q,x,i);ins(q,y,i);}//++i,怎样输入
      for(i=1;i<=n;++i){if(!r[i]){tj(i);break;}}//!,++i
      for(i=0;i<m;++i)printf("%d ",ans[i]);// ++i
    }

    总结:一定要仔细

  • 相关阅读:
    MiniOS系统
    《硅谷传奇》
    《构建之法》1—3章
    学术诚信与职业道德
    Sprint2
    Scrum 项目 7.0 Sprint回顾
    Scrum 项目 6.0 sprint演示
    Scrum 项目 5.0
    Scrum 项目4.0
    操作系统 实验三 进程调度模拟程序
  • 原文地址:https://www.cnblogs.com/linzeli/p/6714404.html
Copyright © 2011-2022 走看看