Problem
Thought
本想像游走那题一样如spfa暴力更新每一个点的线性基,但那样的复杂度十分玄学,个人认为用来骗分还是有点用的
Solution
考虑到对于一条从1到n的路径一定是由一条从1到n的简单路径加上若干个环组成,所以可以预处理处图中的环(不一定要将所有环处理,因为两个相交的小环异或起来可以替代这两个环合起来的大环),可以用 O(n+m) O ( n + m ) 的时间处理
将所有的环的权值异或和放进线性基里
将从1到n的任意一条路径权值异或和作为初始值(因为若有另一条更优的路径,则这两条路径构成一个环,而这个环已经在线性基里了)
求这个初始值在这个线性基里能取到的最大值
Code
#include<cctype>
#include<cstdio>
using namespace std;
typedef long long ll;
#define rg register
template <typename _Tp> inline _Tp read(_Tp&x){
rg char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
const int N=50100,M=62;
struct Edge{int v,nxt;ll w;}a[N<<2];
int head[N];ll dis[N],b[N<<2],t[M+10];
char vis[N];
int n,m,_,tot;
inline void add(int u,int v,ll w){a[++_].v=v,a[_].w=w,a[_].nxt=head[u],head[u]=_;}
void dfs(int x){
vis[x]=1;
for(int i=head[x];i;i=a[i].nxt)
if(vis[a[i].v])b[++tot]=dis[x]^dis[a[i].v]^a[i].w;
else {dis[a[i].v]=dis[x]^a[i].w;dfs(a[i].v);}
return ;
}
int main(){
read(n);read(m);
int x,y;ll z;
for(rg int i=0;i<m;++i)read(x),read(y),read(z),add(x,y,z),add(y,x,z);
dfs(1);
for(rg int i=1;i<=tot;++i)
for(rg int j=M;~j;--j)
if((b[i]>>j)&1)
if(t[j])b[i]^=t[j];
else {t[j]=b[i];break;}
ll ans=dis[n];
for(rg int j=M;~j;--j)
if((ans^t[j])>ans)ans^=t[j];
printf("%lld\n",ans);
return 0;
}