原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=2115
Input
第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。
Output
仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。
Sample Input
5 7
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2
Sample Output
6
本题因为可以重复走点和边,所以要用异或的性质就是两次异或会抵消。所以本题有个性质就是任何一条路径
1
~
于是简化问题后,我们有一个数必选,其他有若干个数可以选,最终要取一些数使得异或和最大。这时候要用到一个东西叫线性基。当判断一个二进制是否可以用一堆数异或起来时,可以将这些数简化到
logD
级别,这里的
D
表示数的大小。具体方法:从高位到地位每次选一个这位上是
之所以WA了好多次是因为当把
1
左移到int64级别这个
type
edge=record
x,y,next:longint;
v:int64;
end;
const
MAXN=200050;
var
map:array[0..MAXN] of edge;
vis:array[0..MAXN] of boolean;
first:array[0..MAXN] of longint;
path,c:array[0..MAXN] of int64;
x:array[0..63] of int64;
n,m,s,i,a,b,j,k,cnt:longint;
e,v:int64;
procedure ins(x,y:longint;v:int64);
begin
inc(s);map[s].x:=x;map[s].y:=y;map[s].v:=v;
map[s].next:=first[x];first[x]:=s;
end;
procedure dfs(x:longint);
var
t,y:longint;
begin
vis[x]:=true;
t:=first[x];
while (t>0) do
begin
y:=map[t].y;
if (not vis[y])
then
begin
path[y]:=path[x] xor map[t].v;
dfs(y);
end
else
begin
inc(cnt);
c[cnt]:=path[x] xor map[t].v xor path[y];
end;
t:=map[t].next;
end;
end;
begin
read(n,m);
e:=1;
s:=0;
for i:=1 to m do
begin
read(a,b,v);
ins(a,b,v);
ins(b,a,v);
end;
fillchar(vis,sizeof(vis),false);
cnt:=0;
dfs(1);
fillchar(vis,sizeof(vis),false);
for i:=63 downto 0 do
begin
x[i]:=0;
for j:=1 to cnt do
if (not vis[j])and(c[j] and (e << i)>0) then
begin
x[i]:=c[j];vis[j]:=true;
for k:=1 to cnt do
if (not vis[k])and(c[k] and (e << i)>0)
then c[k]:=c[k] xor c[j];
break;
end;
end;
for i:=63 downto 0 do
if (path[n] and (e << i)=0)
then path[n]:=path[n] xor x[i];
writeln(path[n]);
end.