( ext{Solution:})
第一次见的套路 记录一下
首先观察到路径,而且 (n) 很大,往最短路方面想,但是一个异或最大值就直接把最短路给干掉了
考虑什么东西可以维护形如 选出一些数使得异或和最大 的问题?——线性基。
那么重新分析题目,我们被要求找到一条路径满足异或和最大,而我们不知道如何决策是最优的……
考虑分析一下最优答案的状态。我们发现,所有可能构成的答案的路径的并集中,必定有环。因为它们的起点终点都一样。
而环又有什么性质?显然可以来回走对吧。这就让我们想起了对应于线性基上选不选的决策。
那么,环现在是唯一自由的因素了。我们现在被要求选出一些数使得 (1) 可以通过它们到达 (n) 并且异或和最大化。
而所有路径都会形成环,也就是说,每条路径都可以通过 异或上一个环 来转化为其他路径。
那这不就和用线性基维护环权值配对了吗。所以只需要 (dfs) 找环加上线性基维护贪心即可。
复杂度 (O(nlog n)) 注意代码里面直接把线性基消成对角矩阵了。
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=4e5+10;
inline int read(){
int s=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch)){s=s*10+ch-'0';ch=getchar();}
return s;
}
int n,m,head[N],tot;
struct E{int nxt,to,dis;}e[N];
int val[N],vis[N];
struct Line_Base{
int p[62];
void insert(int x){
for(int i=61;~i;--i){
int v=x>>i&1;
if(!v)continue;
if(p[i])x^=p[i];
else{
p[i]=x;
for(int j=i-1;~j;--j)if(p[i]>>j&1)p[i]^=p[j];
for(int j=61;j>i;--j)if(p[j]>>i&1)p[j]^=p[i];
return;
}
}
}
int query(int v){
for(int i=61;~i;--i)if((v^p[i])>v)v^=p[i];
return v;
}
}U;
inline void link(int x,int y,int w){e[++tot]=(E){head[x],y,w};head[x]=tot;}
void dfs(int x){
vis[x]=1;
for(int i=head[x];i;i=e[i].nxt){
int j=e[i].to;
if(!vis[j]){
val[j]=val[x]^e[i].dis;
dfs(j);
}
else{
int v=val[x]^val[j]^e[i].dis;
if(!v)continue;
U.insert(v);
}
}
}
signed main(){
freopen("in.txt","r",stdin);
n=read();m=read();
for(int i=1;i<=m;++i){
int x=read(),y=read(),z=read();
link(x,y,z);link(y,x,z);
}
dfs(1);
printf("%lld
",U.query(val[n]));
return 0;
}