方法:高斯消元
解析:不怎么好想的一道题,不过如果想到的话那就是水题一个了。
首先明确一些概念
简单路径:顶点序列中顶点不重复出现的路径。
简单环:在一个回路中,若除第一个与最后一个顶点外,其余顶点不重复出现的回路称为简单回路(简单回路)。
然后呢明确题里说的是什么?
找一条1到n的路径使得所有路径上的边权异或和最大。
那么我们可以拆分一下,这条1到n的路径我们看做两个部分组成:一条简单路径从1到n,以及任意简单环。
这样就比较明了了,然后我们发现,这个简单路径其实找一条就可以了,由一个数异或同一个数两次则不改变这个数这条性质,我们可以知道,其实找到的1到n的路径任意的添加简单环就会成为不同的1到n的路径,也就是说我们可以找到一个基准简单路径异或值。然后我们预处理出所有简单环的异或和。将这道题完美的转化为n个环的异或和已知,现有一个定值m,在这n个数中选择任意个数对m进行异或使得最终的m最大。
这一看我们转化的东西,那就是高斯消元解异或方程组啊,直接水。
不过高斯消元还是调了一阵!!
代码:
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 50010
#define M 100100
using namespace std;
typedef long long ll;
int n,m,cnt,tot;
struct node
{
int to,next;
ll val;
}edge[M<<1];
int head[N];
int vis[N];
ll dis[N];
ll circle[M<<1];
void init()
{
memset(head,-1,sizeof(head));
cnt=1;
}
void edgeadd(int from,int to,ll val)
{
edge[cnt].to=to,edge[cnt].val=val;
edge[cnt].next=head[from];
head[from]=cnt++;
}
void dfs(int now)
{
vis[now]=1;
for(int i=head[now];i!=-1;i=edge[i].next)
{
int to=edge[i].to;
if(vis[to])
{
if(!(dis[now]^dis[to]^edge[i].val))continue;
circle[++tot]=dis[now]^dis[to]^edge[i].val;
}else
{
dis[to]=dis[now]^edge[i].val;
dfs(to);
}
}
}
void gauss()
{
int flag=1,j;
for(ll i=(1ll<<62);i;i>>=1)
{
for(j=flag;j<=tot;j++)
{
if(circle[j]&i)break;
}
if(j==tot+1)continue;
swap(circle[flag],circle[j]);
flag++;
for(int k=1;k<=tot;k++)
{
if(k==flag-1)continue;
if(circle[k]&i)circle[k]^=circle[flag-1];
}
}
}
int main()
{
init();
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;
ll val;
scanf("%d%d%lld",&x,&y,&val);
edgeadd(x,y,val);
edgeadd(y,x,val);
}
dfs(1);
gauss();
for(int i=1;i<=tot;i++)
{
if((circle[i]^dis[n])>dis[n])dis[n]^=circle[i];
}
printf("%lld\n",dis[n]);
}