给一张无向图,求最大路径xor和
位之间会相互影响所以不能拆开分别放
找出一组环可表示图里所有路径
路径->基础路径^环集合
转化成给n个数求子集xor最大是多少
a b c 和a a^b c的表示能力是一样的
可以利用高斯消元的想法消成三角形
再将剩下的数异或起来
复杂度:
消元 O(64)枚举变量*O(n)消其余*O(1)消一个
嗯对就这样
但是里面要用到线性基
这个玩意比较玄
看到了一个比较好的讲线性基的blog
在这:
https://blog.csdn.net/qaq__qaq/article/details/53812883
但是呢还有一种不用线性基的
而且也非常好想
在下面代码里有
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define N 50005
#define M 200005
#define LL long long
using namespace std;
int n,m,head[N],cnt,pri,tot;
LL a[N],b[65],cir[M],ans;
bool vis[N];
struct node{
int to,nxt;
LL w;
}edge[M];
inline LL rd(){
LL x=0,f=1; char c=' ';
while(c<'0' || c>'9') {if(c=='-') f=-1;c=getchar();}
while(c<='9' && c>='0') x=x*10+c-'0',c=getchar();
return x*f;
}
void add(int x,int y,LL z){
cnt++;
edge[cnt].to=y;
edge[cnt].nxt=head[x];
edge[cnt].w=z;
head[x]=cnt;
}
void dfs(int u){
vis[u]=1;
for(int i=head[u];i;i=edge[i].nxt){
int v=edge[i].to;
if(!vis[v]) a[v]=a[u]^edge[i].w,dfs(v);
else cir[++tot]=a[v]^a[u]^edge[i].w;
}
return;
}
void Gauss(){
for(int i=1;i<=tot;i++)//构造线性基
for(int j=62;j>=0;j--){
if(!(cir[i]>>j)) continue;
if(!b[j]) {b[j]=cir[i];break;}
cir[i]^=b[j];
}
for(int i=62;i>=0;i--)
ans=max(ans,ans^b[i]);
}
//还有一种和普通高斯消元很像的方法qwq很好理解,如下:
/*
void Gauss(){
for(int i=1;i<=tot;i++){
if(!cir[i]) continue;
int tar=i;
for(int j=i+1;j<=tot;j++){
if(cir[j]>cir[tar]) tar=j;//找到最大的系数
}
if(tar!=i) swap(cir[tar],cir[i]);
int aim=0;
LL x=cir[i];
while(x){ //找到最高位的1
aim++;
x>>=1;
}
aim--;//这个地方要减1的···
for(int j=1;j<=tot;j++){
if(j==i) continue;
if(cir[j]&(1LL<<aim)) cir[j]^=cir[i]; //aim写成j wa了无数次,讲真样例真的水··写成啥样都能过
}//如果这个数的aim位有1就把它消掉
}
for(int i=1;i<=tot;i++)
ans=max(ans,ans^cir[i]);
}
*/
int main(){
n=rd(); m=rd();
for(int i=1;i<=m;i++){
int x=rd(),y=rd(); LL z=rd();
add(x,y,z); add(y,x,z);
}
dfs(1);
ans=a[n];//任取一条从1到n的路径,并得到其xor和
Gauss();
printf("%lld\n",ans);
return 0;
}