版权声明:因为我是蒟蒻,所以请大佬和神犇们不要转载(有坑)的文章,并指出问题,谢谢 https://blog.csdn.net/Deep_Kevin/article/details/83756285
正题
这一题挺水的?
直接随便求一条1到n的路径异或和,建出Dfs树,每一条返祖边与两点之间路径异或和组成环,扔进线性基,最后维护一遍即可。
首先证明为什么只用扔返祖环和为什么可以扔环?
先解决第二个问题,每一个环肯定可以从1走到其中的某个点上,遍历一遍这个环,在从开始遍历的那个点回去。
那么1到这个点就被遍历了两遍,异或和为0,剩下的环算了一次异或值。
然后解决第一个问题,因为不是返祖环的环可以有返祖环异或而成。很明显,自己画图即可。
那么我们证明了只有环才能带来价值。
最后,为什么随便选一条路径?
因为如果有多条路径,那么他们两两成环,肯定可以异或出来另一条路径。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
using namespace std;
int n,m;
struct edge{
int y,next;
long long c;
}s[200010];
int first[50010],len=0;
bool tf[50010];
long long dis[50010];
long long p[65];
void ins(int x,int y,long long c){
len++;
s[len]=(edge){y,first[x],c};first[x]=len;
}
void insert(long long x){
for(int i=63;i>=0;i--)
if(x>>i){
if(p[i]) x^=p[i];
else {p[i]=x;break;}
}
}
void dfs(int x,long long t){
tf[x]=true;dis[x]=t;
for(int i=first[x];i!=0;i=s[i].next)
if(tf[s[i].y]) insert(t^s[i].c^dis[s[i].y]);
else dfs(s[i].y,dis[x]^s[i].c);
}
int main(){
scanf("%d %d",&n,&m);
int x,y;
long long c;
for(int i=1;i<=m;i++){
scanf("%d %d %lld",&x,&y,&c);
ins(x,y,c);
ins(y,x,c);
}
dfs(1,0);
long long ans=dis[n];
for(int i=63;i>=0;i--) ans=max(ans,ans^p[i]);
printf("%lld",ans);
}