zoukankan      html  css  js  c++  java
  • 家谱 并差集

    题意/Description

          现代的人对于本家族血统越来越感兴趣, 现在给出充足的父子关系, 请你编写程序找到 某个人的最早的祖先。


    读入/Input

           输入文件由多行组成, 首先是一系列有关父子关系的描述, 其中每一组父子关系由二行 组成,用#name 的形式描写一组父子关系中的父亲的名字,用+name 的形式描写一组父子关 系中的儿子的名字;接下来用?name 的形式表示要求该人的最早的祖先;最后用单独的一个 $表示文件结束。规定每个人的名字都有且只有 6 个字符,而且首字母大写,且没有任意两 个人的名字相同。最多可能有 1000 组父子关系,总人数最多可能达到 50000 人,家谱中的 记载不超过 30 代。 


    输出/Output

           按照输入文件的要求顺序,求出每一个要找祖先的人的祖先,格式:本人的名字+一个 空格+祖先的名字+回车。


    题解/solution

           题目很简单,第一眼看就是并差集,小case啦。后来才发现不是就是Time Limit Exceed就是Wrong Answer大哭所以我们开个哈希表来储存名字(最好把字符转化为数字),可以加快速度。然后才发现哈希表不能太大,当然不能太小。就对了。大笑


    代码/Code

     

    var
      h2:array [0..150000] of longint;
      h1:array [0..150000] of string;
      f:array [0..60001] of string;
      a:array [0..60001] of longint;
      t1,t2,k:longint;
      s:string;
      c:char;
    function hash(s:string):longint;
    var
      i:longint;
    begin
      hash:=0;
      for i:=1 to length(s) do
        hash:=hash*4+ord(s[i]);
    end;
    
    function fd(s:string):longint;
    var
      x:longint;
    begin
      x:=hash(s);
      while h1[x]<>'' do
        begin
          if h1[x]=s then exit(h2[x]);
          inc(x);
          if x>150000 then x:=0;
        end;
      exit(0);
    end;
    
    procedure ins(s:string;a:longint);
    var
      i,x:longint;
    begin
      x:=hash(s);
      while h1[x]<>'' do
        begin
          inc(x);
          if x>150000 then x:=0;
        end;
      h1[x]:=s; h2[x]:=a;
    end;
    
    function find(x:longint):longint;
    var
      y,t,k:longint;
    begin
      y:=x;
      while a[y]>0 do
        y:=a[y];
      k:=y;
      y:=x;
      while a[y]>0 do
        begin
          t:=a[y];
          a[y]:=k;
          y:=t;
        end;
      find:=k;
    end;
    
    procedure union(x,y:longint);
    var
      u,v:longint;
    begin
      u:=find(x);
      v:=find(y);
      a[v]:=u;
    end;
    
    procedure init;
    var
      i:longint;
    begin
      for i:=1 to 150000 do
        begin
          h1[i]:=''; h2[i]:=0;
        end;
      while 1=1 do
        begin
          readln(s);
          if s='$' then halt;
          c:=s[1]; delete(s,1,1);
          t1:=fd(s);
          if t1=0 then
            begin
              inc(k); f[k]:=s; t1:=k; ins(s,k);
            end;
          if c='#' then
            t2:=t1;
          if c='+' then
            union(t2,t1);
          if c='?' then
            begin
              writeln(s,' ',f[find(t1)]);
            end;
        end;
    end;
    
    begin
      init;
    end.
    



  • 相关阅读:
    038 Count and Say 数数并说
    037 Sudoku Solver 解数独
    036 Valid Sudoku 有效的数独
    035 Search Insert Position 搜索插入位置
    bzoj1202 [HNOI2005]狡猾的商人
    USACO45 lights 电灯(折半搜索)
    USACO44 TimeTravel 时间旅行(链表)
    USACO35 翻转奶牛(尺取法)
    bzoj1833: [ZJOI2010]count 数字计数&&USACO37 Cow Queueing 数数的梦(数位DP)
    USACO26 moofest 奶牛集会(归并排序)
  • 原文地址:https://www.cnblogs.com/zyx-crying/p/9319698.html
Copyright © 2011-2022 走看看