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.