bzoj 2115 路径xor和最大值

首先我们可以将这张图转化为一棵树,其中可能有好多环,肯定是从1走到N,其中可能经过好多环,

因为我们不走N在的一支,最后还是会走回来,因为a xor b xor b=a,所以相当于没走,就是走了个环,

那么我们这个题可以转化成有若干个环的值,还有1-n的值,在环中全任意个,xor起来再xor 1-n的,

使最后最大。

求环的时候我们可以记下每个点的一个值,代表从1到这个点的路径值xor,用size表示(我英语不好。。。)

那么我们做一遍dfs,如果X访问到已经走过的点P了,那么就出现了环,环中的值就是SIZE[p] xor size[x] xor len[q]

这样我们就得到了环的值。

这里的环不一定是所有的环,可能有些环得不到,但是通过已知的值可以xor出来

那么问题就被成功的转化了,这时我们需要了解一些性质

假设集合A,其中我们将ai替换成ai xor a[j] i<>j,那么得到的新集合,这个集合中元素能xor出的值于集合A相同

那么我们就用类似于高斯消元的方法,将每个数(环的值)弄成二进制来看(只是来看),从高位找起,如果所有二进制

最高位是i,那么找到一个最高位是I的元素,用a[i] xor a[j] 替换所有最高位是I的元素j,那么这个集合可以看成是不变的

(能得出的值不变),并且将I元素移出A集合,直到集合中没有数为止

那么我们可以得到一些移出集合的值(也叫做第I位的基),我们从最高位开始贪心,设1-n的xor是ans,那么我们看ans的I位

是不是1,如果不是那么就xor上第I位的基,最后输出ans就行了

/**************************************************************

    Problem: 2115

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:1520 ms

    Memory:8256 kb

****************************************************************/

 

//By BLADEVIL

var

    n, m                            :int64; 

    pre, other                      :array[0..200010] of int64; 

    len                             :array[0..200010] of int64; 

    last                            :array[0..50010] of int64; 

    l                               :int64; 

    a                               :array[0..200010] of int64; 

    flag                            :array[0..200010] of boolean; 

    size                            :array[0..50010] of int64; 

    tot                             :int64; 

    ans                             :int64;

     

procedure swap(var a,b:int64);

var

    c                               :int64;

begin

    c:=a; a:=b; b:=c;

end;    

 

procedure connect(x,y:int64;z:int64); 

begin

    inc(l); 

    pre[l]:=last[x]; 

    last[x]:=l; 

    other[l]:=y; 

    len[l]:=z; 

end; 

 

procedure dfs(x:int64); 

var

    q, p                            :int64; 

begin 

    flag[x]:=true;

    q:=last[x]; 

    while q<>0 do

    begin

        p:=other[q]; 

        if not flag[p] then

        begin

            size[p]:=size[x] xor len[q]; 

            dfs(p); 

        end else

        begin

            inc(tot); 

            a[tot]:=size[x] xor len[q] xor size[p]; 

            if a[tot]=0 then dec(tot); 

        end; 

        q:=pre[q]; 

    end; 

end; 

 

procedure init; 

var

    i                               :longint; 

    x, y                            :int64; 

    z                               :int64;

begin

    read(n,m); 

    for i:=1 to m do

    begin

        read(x,y,z); 

        connect(x,y,z); 

        connect(y,x,z); 

    end; 

    dfs(1); 

end; 

    

procedure qs(low,high:int64);

var

    i, j                            :longint;

    xx                              :int64;

begin

    i:=low; j:=high; xx:=a[(i+j) div 2];

    while i<j do

    begin

        while a[i]>xx do inc(i);

        while a[j]<xx do dec(j);

        if i<=j then

        begin

            swap(a[i],a[j]);

            inc(i); dec(j);

        end;

    end;

    if i<high then qs(i,high);

    if j>low then qs(low,j);

end;

    

procedure main;

var

    i, j, k                         :longint;

    cur                             :int64;

     

begin

    fillchar(flag,sizeof(flag),false);

    cur:=1<<62;

    for i:=0 to 62 do

    begin

        for j:=1 to tot do

        if not flag[j] then

            if a[j] and cur=cur then

            begin

                flag[j]:=true;

                for k:=1 to tot do

                    if (not flag[k]) and (a[k] and cur=cur) then

                        a[k]:=a[k] xor a[j];

                break;

            end;

        cur:=cur>>1;

    end;

    qs(1,tot);

    ans:=size[n];

    for i:=1 to tot do

    begin

        if a[i]=0 then break;

        if ans xor a[i]>ans then ans:=ans xor a[i];

    end;

    writeln(ans);

end;

    

begin

    init; 

    main;

end.

 

你可能感兴趣的:(ZOJ)