• 【NOIP2012模拟10.27】祖孙询问


    Description

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

    Input

    输入第一行包括一个整数n表示节点个数。
    接下来n行每行一对整数对a和b表示a和b之间有连边。如果b是-1,那么a就是树的根。
    第n+2行是一个整数m表示询问个数。
    接下来m行,每行两个正整数x和y。

    Output

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

    题解

    DFS序以及各种求LCA算法均可秒杀此题。

    代码

    type
      arr=record
            y,next:longint;
          end;
    var
      n,m,nm,n_1:longint;
      ls,h:array [0..40001] of longint;
      go:array [0..40001,0..20] of longint;
      e:array [0..80001] of arr;
    procedure add(o,p:longint);
    begin
      inc(nm);
      with e[nm] do
        begin
          y:=p; next:=ls[o]; ls[o]:=nm;
        end;
      inc(nm);
      with e[nm] do
        begin
          y:=o; next:=ls[p]; ls[p]:=nm;
        end;
    end;
    
    procedure init;
    var
      i,x,y:longint;
    begin
      nm:=0;
      readln(n);
      for i:=1 to n do
        begin
          readln(x,y);
          if y=-1 then n_1:=x
                  else add(x,y);
        end;
    end;
    
    procedure dfs(x:longint);
    var
      i:longint;
    begin
      for i:=1 to 15 do
        begin
          if h[x]<(1 shl i) then break;
          go[x,i]:=go[go[x,i-1],i-1];
        end;
      i:=ls[x];
      while i>0 do
        with e[i] do
          begin
            if y<>go[x,0] then
              begin
                h[y]:=h[x]+1; go[y,0]:=x;
                dfs(y);
              end;
            i:=next;
          end;
    end;
    
    function LCA(x,y:longint):longint;
    var
      t,i:longint;
    begin
      if h[x]<h[y] then
        begin
          t:=x; x:=y; y:=t;
        end;
      t:=h[x]-h[y];
      for i:=15 downto 0 do
        if (t and (1 shl i))<>0 then x:=go[x,i];
      for i:=15 downto 0 do
        if go[x,i]<>go[y,i] then
          begin
            x:=go[x,i];
            y:=go[y,i];
          end;
      if x=y then exit(x);
      exit(go[x,0]);
    end;
    
    procedure main;
    var
      i,x,y,t:longint;
    begin
      dfs(n_1);
      readln(m);
      for i:=1 to m do
        begin
          readln(x,y);
          if x=y then writeln('0') else
            begin
              t:=LCA(x,y);
              if t=x then writeln('1') else
                if t=y then writeln('2') else
                  writeln('0');
            end;
        end;
    end;
    
    begin
      init;
      main;
    end.
    
    
  • 相关阅读:
    毕设问题02-index.jsp跳转html问题
    毕设问题01-html中引入公共部分代码
    毕设开篇
    object和大括号自定义对象
    数组js
    function 方法的使用
    JavaScript01
    CSS属性
    听说不能改日期了
    获取时间
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319583.html
Copyright © 2020-2023  润新知