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.