[luogu] P4151 [WC2011]最大XOR和路径 dfs+线性基

这篇博客讨论了一道算法题,题目要求在含有环的无向有权图中找到一条从1到N的路径,使得路径上所有节点值的异或和最大。作者提到,如果没有环,只需直接计算异或和;但因为存在环,需要考虑环的影响。解决方案是使用DFS求路径异或和,并结合线性基处理环。作者分享了编程过程中遇到的错误和解决办法,并给出了完整的代码实现。
摘要由CSDN通过智能技术生成

前言

传送门 :

题意

给你一个无向有权图(含环),求一条从 1 − N 1 - N 1N的路径上,异或和最大

思路

这道题,虽然看完题解之后感觉异常简单,但是撸起来还是非常困难的

首先 :
如果没有环,那么只需要求 v [ 1 ] x o r . . . . . v [ N ] v[1] xor.....v[N] v[1]xor.....v[N]即可

但是因为有环的参与,导致答案会被环更新,由于到环的距离来回一次所以不考虑

因此答案最后是 v [ 1 ] x o r . . . v [ N ] v[1] xor ...v[N] v[1]xor...v[N]

但是可能存在多条直达 1 − N 1-N 1N的路径,但是因为无向图,多条路径可看成一个环,因此不考虑

所以最后我们只需要求 一条路径 xor 多个环 m a x max max

前者可以使用 d f s dfs dfs求出,后者使用 线性基 即可

参考 : 博文链接

虽然简单,但是 d e b u g debug debug半小时之久
第一 : 没看 M M M的范围,导致 R E RE RE
第二 : 没开 L L LL LL
第三 : 异或优先级低于 > > >

Mycode

#define int long long
const int N  = 1e5+100;
struct node{
	int to,val;
};
vector<node> g[N];

ll st[N],dist[N];
ll p[N];

int h[N*2],e[N*2],ne[N*2],w[N*2],idx;
void add(int a,int b,int c){
	e[++idx] =  b , ne[idx] = h[a] , w[idx] = c,h[a] = idx;
}
void xor_insert(ll x){
	for(int i = 63 ; i>= 0 ; i -- ){
		if(!(x >>(ll)i)){
			continue;
		}
		if(!p[i]){
			p[i] = x;
			break;
		}
		x ^= p[i];
	}
}

void dfs(int u,ll val){
	dist[u] = val;
	st[u] = 1;
	for(int i =h[u];i;i=ne[i]){
		int j = e[i];
	
		
		if(!st[j]) dfs(j,val^w[i]);
		else xor_insert(val^dist[j]^w[i]);
	}
	// for(auto x : g[u]){
		// if(!st[x.to]) dfs(x.to,val^x.val);
		// else xor_insert(val^dist[x.to]^x.val);
	// }
}
void solve()
{
	int n,m;
	cin>>n>>m;
	
	for(int i=1;i<=m;i++){
		int a,b,c;cin>>a>>b>>c;
		// g[a].pb({b,c});
		// g[b].pb({a,c});
		add(a,b,c);add(b,a,c);
		
	}

	dfs(1,0);
	ll ans =  dist[n];

	
	for(int i =63;i>=0;i -- ){
		if( (ans ^p[i]) > ans)
		ans^=p[i];
	}

	cout<<ans <<endl;


}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值