洛谷 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;
}
posted @ 2021-10-28 11:47  尹昱钦  阅读(34)  评论(0编辑  收藏  举报