洛谷 P4151 [WC2011]最大XOR和路径(线性基)
传送门
解题思路
非常清新的一道题。
先假设选择了一条1->n的主路径,然后在这条路径上向外拓展。
发现只有环对答案有影响,因为非环的边一定会走两次,异或和为0。
因为图是联通的,所以可以经过任意环,所以可以把所有的环的异或值扔到线性基里。
然后再考虑选择哪一条路径,我们发现若1->n有多条路径,其实这些路径也构成了环,也会被加入到线性基里,这时候随便选一条路径即可。
如何找环用的是题解中的方法,很巧妙。
AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<vector>
using namespace std;
const int maxn=50005;
int cnt,p[maxn],vis[maxn],n,m;
long long dis[maxn],a[maxn];
struct node{
int v,next;
long long w;
}e[maxn*4];
void insert(int u,int v,long long w){
cnt++;
e[cnt].v=v;
e[cnt].next=p[u];
e[cnt].w=w;
p[u]=cnt;
}
void update(long long x){
if(!x) return;
for(int i=63;i>=0;i--){
if(x&(1ll<<i)){
if(a[i]) x^=a[i];
else{
a[i]=x;
return;
}
}
}
}
void dfs(int u,long long res){
vis[u]=1;
dis[u]=res;
for(int i=p[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(vis[v]) update(res^e[i].w^dis[v]);
else dfs(v,res^e[i].w);
}
}
long long query(long long x){
for(int i=63;i>=0;i--){
if((x^a[i])>x) x^=a[i];
}
return x;
}
int main(){
ios::sync_with_stdio(false);
memset(p,-1,sizeof(p));
cin>>n>>m;
for(int i=1;i<=m;i++){
int u,v;long long w;
cin>>u>>v>>w;
insert(u,v,w);
insert(v,u,w);
}
dfs(1,0);
cout<<query(dis[n]);
return 0;
}