不知道线性基是什么东西的可以看看蒟蒻的
首先看到异或就想到线性基
我们考虑有一条路径,那么从这条路径走到图中的任意一个环再走回这条路径上,对答案的贡献是这个环的异或和,走到这个环上的路径对答案是没有影响的
以这张(偷来的)图为例
从$1$走到$n$,先走到环再走回来,那么到环上那条路径(红色的)被走了两次,那么异或之后为0,对答案无贡献
那么我们可以随意走一条路径,然后把图上所有环丢到线性基里,求一下在这些线性基下最大能异或和是多少,就是个板子了
那么考虑一下走的路径会不会对答案有影响
依然考虑(盗来的)图
一开始走的是$B$这条路径,但实际上$A$更优,那么$B$路径异或上这整个大环的权值就是$A$路径的权值
找环可以直接dfs
然后没有然后了
1 //minamoto 2 #include3 #include 4 #include 5 #define ll long long 6 using namespace std; 7 #define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++) 8 char buf[1<<21],*p1=buf,*p2=buf; 9 inline ll read(){10 #define num ch-'0'11 char ch;bool flag=0;ll res;12 while(!isdigit(ch=getc()))13 (ch=='-')&&(flag=true);14 for(res=num;isdigit(ch=getc());res=res*10+num);15 (flag)&&(res=-res);16 #undef num17 return res;18 }19 ll b[65];20 void insert(ll x){21 for(int i=63;i>=0;--i){22 if((x>>i)&1){23 if(!b[i]){24 b[i]=x;return;25 }26 x^=b[i];27 }28 }29 }30 ll query(ll x){31 ll res=x;32 for(int i=63;i>=0;--i)33 if((res^b[i])>res) res^=b[i];34 return res;35 }36 const int N=5e4+5,M=2e5+5;37 int head[N],Next[M],ver[M],tot;ll edge[M];38 inline void add(int u,int v,ll e){39 ver[++tot]=v,Next[tot]=head[u],head[u]=tot,edge[tot]=e;40 }41 int vis[N];ll del[N];42 void dfs(int u,ll res){43 del[u]=res,vis[u]=1;44 for(int i=head[u];i;i=Next[i])45 if(!vis[ver[i]]) dfs(ver[i],res^edge[i]);46 else insert(res^edge[i]^del[ver[i]]);47 }48 int main(){49 // freopen("testdata.in","r",stdin);50 int n,m,u,v;ll e;n=read(),m=read();51 for(int i=1;i<=m;++i)52 u=read(),v=read(),e=read(),add(u,v,e),add(v,u,e);53 dfs(1,0);54 printf("%lld\n",query(del[n]));55 return 0;56 }