zoukankan      html  css  js  c++  java
  • CODEVS1187 Xor最大路径 (Trie树)

      由于权值是在边上,所以很容易发现一个性质:d(x,y)=d(x,root) xor d(y,root)。

      因为有了这个性质,那么就很好做了。对于每一个点统计到root的距离,记为f 数组。

      将f数组里的每个值插进按照二进制位插进字典树里面。

      枚举每一个点,然后在字典树中搜索最大的xor值就可以了。

    Program CODEVS1187;
    const maxn=100008;
    type arr=record
            u,v,w,next:int64;
            end;
    type arr1=record
            next:array[0..1] of longint;
            end;
    var eg:array[0..maxn*2] of arr;
        last:array[0..maxn] of longint;
        fa:array[0 ..maxn] of longint;
        f:array[0..maxn] of int64;
        T:array[0..maxn*32] of arr1;
        a:array[0..100] of longint;
        n,u,v,w,root,mx,num,m,k,sum,ans,now:int64;
        i,j:longint;
    procedure add(u,v,w:longint);
    begin
      inc(j);
      eg[j].u:=u;
      eg[j].v:=v;
      eg[j].w:=w;
      eg[j].next:=last[u];
      last[u]:=j;
    end;
    procedure dfs(u:longint;sum:int64;fa:longint);
    var i:longint;
    begin
      f[u]:=sum;    
      i:=last[u];
      while i<>0 do
        begin
          if eg[i].v<>fa then
          dfs(eg[i].v,sum xor eg[i].w,u);
          i:=eg[i].next;
        end;
    end;
    begin
      readln(n);
      for i:=1 to n-1 do
        begin
          readln(u,v,w);
              add(u,v,w);
          add(v,u,w);
        end;
      root:=1;
      dfs(root,0,0);
    {---------------------------------------------------}
      mx:=0;
      for i:=1 to n do if f[i]>mx then mx:=f[i];
      j:=mx; num:=0;
      while j>0 do
        begin
          inc(num);
          j:=j div 2;
        end;
      m:=num; k:=1;
      for i:=1 to n do
        begin
          fillchar(a,sizeof(a),0);
          j:=f[i]; num:=0;
          while j>0 do
            begin
              inc(num);
              a[num]:=j mod 2;
              j:=j div 2;
            end;
          now:=1;
          for j:=m downto 1 do
            if T[now].next[a[j]]<>0 then now:=T[now].next[a[j]] else
              begin
                inc(k);
                T[now].next[a[j]]:=k;
                now:=k;
              end;
        end;
      ans:=0;
      for i:=1 to n do
        begin
          fillchar(a,sizeof(a),0);
          j:=f[i]; num:=0;
          while j>0 do
            begin
              inc(num);
              a[num]:=j mod 2;
              j:=j div 2;
            end;
          now:=1; sum:=0;
          for j:=m downto 1 do
            if T[now].next[1-a[j]]<>0 then
              begin
                sum:=sum*2+1-a[j];
                now:=T[now].next[1-a[j]];
              end
            else
              begin
                sum:=sum*2+a[j];
                now:=T[now].next[a[j]];
              end;
          if sum xor f[i]>ans then ans:=sum xor f[i];
        end;
      writeln(ans);
    end.
  • 相关阅读:
    UVA 10480 Sabotage (最大流最小割)
    bzoj2002 [Hnoi2010]Bounce 弹飞绵羊 (分块)
    poj3580 SuperMemo (Splay+区间内向一个方向移动)
    bzoj1500: [NOI2005]维修数列 (Splay+变态题)
    hdu3436 Queue-jumpers(Splay)
    hdu4710 Balls Rearrangement(数学公式+取模)
    hdu1890 Robotic Sort (splay+区间翻转单点更新)
    zoj2112 Dynamic Rankings (主席树 || 树套树)
    poj3581 Sequence (后缀数组)
    notepa++ Emmet的安装方法
  • 原文地址:https://www.cnblogs.com/rpSebastian/p/4168012.html
Copyright © 2011-2022 走看看