cunzai_zsy0531

关注我

P4151 [WC2011]最大XOR和路径 题解

题面

首先考虑没有环的情况,那么答案肯定就是 \(1\)\(n\) 简单路径的边权异或和。如果出现环,设这个环边权异或和为 \(c\),从这条 \(1\)\(n\) 简单路径到这个环的路径边权异或和为 \(k\),那么答案为 \(dis_n\oplus k\oplus c\oplus k\)

通过上面的分析,可以发现,答案就是 \(dis_n\) 与所有环的异或和这些数能够异或起来的最大值,这显然可以使用线性基来快速解决。注意 \(dis_n\) 是任意一条 \(1\)\(n\) 的路径异或和即可,因为如果还有其他路径,一定会出现在环的那部分内,贡献是一样的。复杂度 \(O(n\log v)\)

点击查看代码
#include<iostream>
#include<cstdio>
typedef long long ll;
inline ll rd(){
	ll res=0;char c=getchar();
	for(;!isdigit(c);c=getchar());
	for(;isdigit(c);c=getchar())res=(res<<1)+(res<<3)+(c-'0');
	return res;
}
const int N=1e5+13,M=62+13;
struct Onbase{
	ll p[M];
	inline void insert(ll x){
		for(int i=62;i>=0;--i){
			if(!(x&(1ll<<i))) continue;
			if(!p[i]){p[i]=x;break;}
			x^=p[i];
		}
	}
}Base;
struct Edge{int v;ll w;int nxt;}e[N<<1];
int n,m,h[N],tot;
ll dis[N];
bool vis[N];
inline void add_edge(int u,int v,ll w){e[++tot]=(Edge){v,w,h[u]};h[u]=tot;}
void dfs(int u,ll x){
	vis[u]=1,dis[u]=x;
	for(int i=h[u];i;i=e[i].nxt){
		int v=e[i].v;ll w=e[i].w;
		if(!vis[v]) dfs(v,x^w);
		else Base.insert(dis[v]^x^w);
	}
}
int main(){
	n=rd(),m=rd();
	for(int i=1;i<=m;++i){
		int u=rd(),v=rd();ll w=rd();
		add_edge(u,v,w),add_edge(v,u,w);
	}
	dfs(1,0);
	ll ans=dis[n];
	for(int i=62;i>=0;--i)
		if((ans^Base.p[i])>ans) ans^=Base.p[i];
	printf("%lld\n",ans);
	return 0;
}
posted @ 2022-05-20 12:04  cunzai_zsy0531  阅读(23)  评论(0编辑  收藏  举报