BZOJ2115 XOR(线性基)

本文介绍了一种求解无向连通图中从节点1到节点n的路径最大异或和的问题。通过DFS找到所有环的异或和,并利用线性基思想选出若干个环,使这些环的异或和达到最大。

前置知识:线性基

题目描述

有一个边权为非负数的无向连通图,节点编号为 1 1 1 n n n。求一条从 1 1 1 n n n的路径,使得路径上经过的边的边权的异或和最大。

路径可以重复经过点和边,当一条边在路径中出现多次时,其权值在计算异或和时也要被计算相应多的次数。


题解

如果图中没有环,那么 1 1 1 n n n的无重边的路径显然是最优的。那么如果有环,我们可以先找到一条从 1 1 1 n n n的路径,算出异或和。然后,用一次dfs求出每个环的异或和。对于一个环,我们可以从 1 1 1 n n n的路径上任意取一个点,从这个点走到环,绕环一圈后走回这个点。环到点的路径被走过两次,异或两次等于不变,所以就相当于原来 1 1 1 n n n的路径的异或和再异或上这个环的异或和。

也就是说,我们要选若干个环,使这些环的异或和最大。那么这道题就变成了求若干个数的最大异或和,可以用线性基来解决。不过需要注意的是, 1 1 1 n n n的路径是必须要选的,不能将这条路径的异或和忽略了。

code

#include<bits/stdc++.h>
using namespace std;
int n,m,x,y,tot,cnt,d[200005],l[200005],r[200005],v[100005];
long long z,ans,w[200005],dis[100005],a[200005],b[105];
void add(int xx,int yy,long long zz){
	l[++tot]=r[xx];d[tot]=yy;r[xx]=tot;w[tot]=zz;
}
void dfs(int u){
	v[u]=1;
	for(int i=r[u];i;i=l[i]){
		if(v[d[i]]){
			a[++cnt]=dis[d[i]]^dis[u]^w[i];
		}
		else{
			dis[d[i]]=dis[u]^w[i];
			dfs(d[i]);
		}
	}
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		scanf("%d%d%lld",&x,&y,&z);
		add(x,y,z);add(y,x,z);
	}
	dfs(1);
	for(int i=1;i<=cnt;i++){
		for(int j=60;j>=0;j--){
			if((a[i]>>j)&1){
				if(b[j]) a[i]^=b[j];
				else{
					b[j]=a[i];break;
				}
			}
		}
	}
	ans=dis[n];
	for(int i=60;i>=0;i--){
		if((ans^b[i])>ans) ans^=b[i];
	}
	printf("%lld",ans);
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值