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
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
Source
线性基
首先建一棵生成树 求出dis[T]把它塞进线性基 每次算答案它为基数
然后考虑所有非树边 设为(u,v) 则把dis[u]^dis[v]^val塞进去
正确性显然
#include<bits/stdc++.h>
using namespace std;
const int maxn=66666;
int n,m,cnt;
struct base
{
long long a[61];
base()
{
for(int i=0;i<=60;i++)
a[i]=0;
}
void add(long long x)
{
for(int i=60;i>=0;i--)
{
if((x>>i)&1)
{
if(!a[i])
{
a[i]=x;
break;
}
x^=a[i];
}
}
}
long long result(long long x)
{
for(int i=60;i>=0;i--)
{
if(!((x>>i)&1))
{
x^=a[i];
}
}
return x;
}
}ans;
struct Edge
{
int u,v;
long long w;
}edge[maxn<<1];
struct E
{
int to,nxt;
long long val;
}e[maxn<<2];
int f[maxn],vis[maxn],head[maxn],fa[maxn];
long long dis[maxn];
int findfa(int x)
{
return f[x]==x?x:f[x]=findfa(f[x]);
}
void addedge(int x,int y,long long z)
{
e[++cnt].to=y;
e[cnt].nxt=head[x];
head[x]=cnt;
e[cnt].val=z;
}
void uni(int x,int y,long long z)
{
f[findfa(x)]=findfa(y);
addedge(x,y,z);
addedge(y,x,z);
}
void dfs(int x)
{
for(int i=head[x];i;i=e[i].nxt)
{
int y=e[i].to;
if(y!=fa[x])
{
fa[y]=x;
dis[y]=dis[x]^e[i].val;
dfs(y);
}
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
f[i]=i;
for(int i=1;i<=m;i++)
scanf("%d%d%lld",&edge[i].u,&edge[i].v,&edge[i].w);
for(int i=1;i<=m;i++)
{
int u=edge[i].u,v=edge[i].v;
int fu=findfa(u),fv=findfa(v);
if(fu!=fv)
{
vis[i]=1;
uni(u,v,edge[i].w);
}
}
dfs(1);
for(int i=1;i<=m;i++)
{
if(!vis[i])
{
int u=edge[i].u,v=edge[i].v;
ans.add(dis[u]^dis[v]^edge[i].w);
}
}
cout<<ans.result(dis[n]);
}