BZOJ2115[Wc2011] Xor

题意让求一条最长XOR路径,隐约觉得和线性基有关

然后我们发现XOR具有自反性,就是说A^B^B=A,然后我们需要一条从1->n的最大路径,我们就可以先找到任意一条路径,然后通过其他路径来更新这条路径,假设现在有一条路径,可以使当前结果增大,那么我们肯定要选他,但是假如当前路径和增大路径没有连接,怎么办?我们通过自反性,中间走过的不必要路程可以通过走两遍来消除,也就是说假如我们可以从当前路径到达另一路径,并且两条路径间的路径要走两遍,显然另一条路径是一个环,所以我们处理处图中所有路径和环的^,然后用所有的环构造线性基,那么我们就可以用构造的线性基去更新开始选的路径

代码

//By AcerMo
#include<cmath>
#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int M=400500;
struct edge
{
	int to;
	long long int cost;
}add;
vector<edge>v[M];
int n,m,cnt=0,vis[M];
long long int w[M],cir[M],b[100];//longlong
inline long long int read()
{
	long long int x=0;char ch=getchar();
	while (ch>'9'||ch<'0') ch=getchar();
	while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	return x;
}//返回类型以及x都是longlong 
inline void dfs(int x)
{
	vis[x]=1;
	for (int i=0;i<v[x].size();i++)
	{
		int go=v[x][i].to;
		long long int pay=v[x][i].cost;
		if (!vis[go]) w[go]=w[x]^pay,dfs(go);
		else cir[++cnt]=w[x]^w[go]^pay;
	}
	return ;
}//dfs找环并处理路径 
int main()
{
	n=read();m=read();
	for (int i=1;i<=m;i++)
	{
		int a=read(),b=read();
		long long int c=read();//注意longlong 
		add.to=b;add.cost=c;v[a].push_back(add);
		add.to=a;add.cost=c;v[b].push_back(add);
	}
	dfs(1);
	long long int ans=w[n];//ans初值为任意一条1->n的路径^ 
	for (int i=1;i<=cnt;i++)
		for (int k=62;~k;k--)
			if (cir[i]&(1LL<<k)) 
				if (!b[k]){b[k]=cir[i];break;}
					else cir[i]^=b[k];
	//构造线性基 
	for (int i=62;~i;i--)
		ans=max(ans,ans^b[i]);
	//求解 
	cout<<ans;
	return 0;			
}

猜你喜欢

转载自blog.csdn.net/acerandaker/article/details/80886323