zoukankan      html  css  js  c++  java
  • LCA倍增算法的错误与模板

    先上我原来的错误的代码

    type
      node=^link;
      link=record
        num:int64;
        next:node;
      end;
    
    var
     fa:array[0..300000,0..100] of int64;
     dep:array[0..300000] of int64;
       nd:array[0..300000] of node;
      b:array[0..300000] of boolean;
      dl:array[0..300000] of int64;
     n,m,maxdep,ans,t1,t2:int64;
     i:longint;
    
     procedure maketree;
     var
      t1,t2,head,tail:int64;
      i,j:longint;
      p:node;
       begin
        
    
         for i:=0 to n do
           b[i]:=false;
    
         for i:=1 to n-1 do
           begin
             read(t1,t2);
               
             new(p);
             p^.num:=t2;p^.next:=nd[t1];nd[t1]:=p;
             new(p);
             p^.num:=t1;p^.next:=nd[t2];nd[t2]:=p;
           end;
    
          new(p);
          head:=1;tail:=1;dl[head]:=1;b[1]:=true;
           while head<=tail do
             begin
               p:=nd[dl[head]];
    
               while p<>nil do
                 begin
                   if b[p^.num]=false then
                     begin
                       inc(tail);
                       dl[tail]:=p^.num;
                       fa[p^.num,0]:=dl[head];
                       dep[p^.num]:=dep[dl[head]]+1;
                       b[p^.num]:=true;
                       if dep[p^.num]>maxdep then maxdep:=dep[p^.num];
                     end;
                   p:=p^.next;
                 end;
    
               inc(head);
             end;
    
          for j:=1 to trunc(ln(maxdep)/ln(2))+1 do
            for i:=0 to n do
              if dep[i]>=1<<j then
                fa[i,j]:=fa[fa[i,j-1],j-1];
       end;
    
      procedure lca(a,b:longint);
      var
       i,t:longint;
        begin
          if dep[a]>dep[b] then
            begin
              t:=a;
              a:=b;
              b:=t;
            end;
    
          if dep[a]<>dep[b] then
            for i:=trunc(ln(dep[b]-dep[a])/ln(2)) downto 0 do
              if dep[b]-1<<i>=dep[a] then
                begin
                   b:=fa[b,i];
                   ans:=ans+1<<i;
                end;
    
         if a<>b then
          for i:=trunc(ln(dep[a])/ln(2)) downto 0 do
            if fa[a,i]<>fa[b,i] then
              begin
                a:=fa[a,i];
                b:=fa[b,i];
                ans:=ans+1<<(i+1);
              end;
    
          if a<>b then inc(ans,2);
        end;
    
      begin
      
        readln(n);
    
        if n=1 then
          begin
            writeln(0);
            halt; 
          end;
    
        maketree;
    
        readln(m);
    
        read(t1);
        for i:=2 to m do
          begin
            read(t2);
         
            lca(t1,t2);
            t1:=t2;
          end;
    
        writeln(ans);
        
    
      end.

    这个写法WA了一个点,答案比标准答案大。

    最后发现可能是ln出现了误差,导致结果偏小,使两点无法移到同层。在后面的移动中无论怎样都无法移到同点,使答案比原来大二

    改正后的模板

    type
      node=^link;
      link=record
        num:int64;
        next:node;
      end;
    
    var
     fa:array[0..300000,0..100] of int64;
     dep:array[0..300000] of int64;
       nd:array[0..300000] of node;
      b:array[0..300000] of boolean;
      dl:array[0..300000] of int64;
      n,m,maxdep,ans,t1,t2:int64;
      i:longint;
    
     procedure maketree;
     var
      t1,t2,head,tail:int64;
      i,j:longint;
      p:node;
       begin
        
    
         for i:=0 to n do
           b[i]:=false;
    
         for i:=1 to n-1 do
           begin
             read(t1,t2);
               
             new(p);
             p^.num:=t2;p^.next:=nd[t1];nd[t1]:=p;
             new(p);
             p^.num:=t1;p^.next:=nd[t2];nd[t2]:=p;
           end;
    
          new(p);
          head:=1;tail:=1;dl[head]:=1;b[1]:=true;
           while head<=tail do
             begin
               p:=nd[dl[head]];
    
               while p<>nil do
                 begin
                   if b[p^.num]=false then
                     begin
                       inc(tail);
                       dl[tail]:=p^.num;
                       fa[p^.num,0]:=dl[head];
                       dep[p^.num]:=dep[dl[head]]+1;
                       b[p^.num]:=true;
                       if dep[p^.num]>maxdep then maxdep:=dep[p^.num];
                     end;
                   p:=p^.next;
                 end;
    
               inc(head);
             end;
    
          for j:=1 to trunc(ln(maxdep)/ln(2))+1 do
            for i:=0 to n do
              if dep[i]>=1<<j then
                fa[i,j]:=fa[fa[i,j-1],j-1];
       end;
    
      procedure lca(a,b:longint);
      var
       i,t:longint;
        begin
          if dep[a]>dep[b] then
            begin
              t:=a;
              a:=b;
              b:=t;
            end;
    
          if dep[a]<>dep[b] then
            for i:=trunc(ln(dep[b]-dep[a])/ln(2))+10 downto 0 do
              if dep[b]-1<<i>=dep[a] then
                begin
                   b:=fa[b,i];
                   ans:=ans+1<<i;
                end;
    
         if a<>b then
          for i:=trunc(ln(dep[a])/ln(2))+10 downto 0 do
            if fa[a,i]<>fa[b,i] then
              begin
                a:=fa[a,i];
                b:=fa[b,i];
                ans:=ans+1<<(i+1);
              end;
    
          if a<>b then inc(ans,2);
        end;
    
      begin
      
        readln(n);
    
        if n=1 then
          begin
            writeln(0);
            halt; 
          end;
    
        maketree;
    
        readln(m);
    
        read(t1);
        for i:=2 to m do
          begin
            read(t2);
         
            lca(t1,t2);
            t1:=t2;
          end;
    
        writeln(ans);
        
    
      end.
  • 相关阅读:
    Redis 记录
    flink 流控机制详解
    备份和快照的区别
    LVS 总结
    Keepalived 总结
    OpenResty 总结
    Lua 总结
    Element-UI 总结
    Java transient 关键字
    Activiti 框架
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/5252868.html
Copyright © 2011-2022 走看看