\(\text{Solution:}\)
第一次見的套路 記錄一下
首先觀察到路徑,而且 \(n\) 很大,往最短路方面想,但是一個異或最大值就直接把最短路給幹掉了
考慮什麼東西可以維護形如 選出一些數使得異或和最大 的問題?——線性基。
那麼重新分析題目,我們被要求找到一條路徑滿足異或和最大,而我們不知道如何決策是最優的……
考慮分析一下最優答案的狀態。我們發現,所有可能構成的答案的路徑的並集中,必定有環。因爲它們的起點終點都一樣。
而環又有什麼性質?顯然可以來回走對吧。這就讓我們想起了對應於線性基上選不選的決策。
那麼,環現在是唯一自由的因素了。我們現在被要求選出一些數使得 \(1\) 可以通過它們到達 \(n\) 並且異或和最大化。
而所有路徑都會形成環,也就是說,每條路徑都可以通過 異或上一個環 來轉化爲其他路徑。
那這不就和用線性基維護環權值配對了嗎。所以只需要 \(dfs\) 找環加上線性基維護貪心即可。
複雜度 \(O(n\log 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\n",U.query(val[n]));
return 0;
}