Description
Input
第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目。 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si
与Ti之间存在 一条权值为 Di的无向边。 图中可能有重边或自环。
Output
仅包含一个整数,表示最大的XOR和(十进制结果),注意输出后加换行回车。
Sample Input
5 7
1 2 2
1 3 2
2 4 1
2 5 1
4 5 3
5 3 4
4 3 2
Sample Output
6
HINT
题解
这条路径一定是由一条从1到n的简单路径与一些环组成的。
因为重复走没有贡献会抵消
任意找出图中一条1到n的路径作为ans初值
预处理出图中每个环的异或值,可以在dfs的时候直接搞出来
做出这些环异或值的线性基,ans在线性基上贪心取即可
当我们想取到任意一个环的异或值时,在同一条路径上来回走一次即可取到,由于来回走不回取到这条路径的异或值,可证明可行性
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL;
struct node{int x,y,next;LL c;}a[210000];int len,last[51000];
void ins(int x,int y,LL c){len++;a[len].x=x;a[len].y=y;a[len].c=c;a[len].next=last[x];last[x]=len;}
bool v[51000];
LL f[2110000],d[51000];
int ln,n,m;
void dfs(int x)
{
v[x]=true;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
if(!v[y])d[y]=d[x]^a[k].c,dfs(y);
else f[++ln]=d[x]^a[k].c^d[y];
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x,y;LL c;
scanf("%d%d%lld",&x,&y,&c);
ins(x,y,c);ins(y,x,c);
}
memset(v,false,sizeof(v));
dfs(1);
LL ans=d[n];
for(int i=1;i<=ln;i++)
{
int p=i;
for(int j=i+1;j<=ln;j++)if(f[p]<f[j])p=j;
swap(f[i],f[p]);
if(f[i]==0){ln=i-1;break;}
for(int k=62;k>=0;k--)
if(f[i]&(1LL<<k))
{
for(int j=i+1;j<=ln;j++)
if(f[j]&(1LL<<k))f[j]^=f[i];
break;
}
}
for(int i=1;i<=ln;i++)ans=max(ans,ans^f[i]);
printf("%lld\n",ans);
return 0;
}