题目大意:给定一个无向图,每条边上有边权,求一条1到n的路径,使路径上权值异或和最大
首先一条路径的异或和可以化为一条1到n的简单路径和一些简单环的异或和
我们首先DFS求出任意一条1到n的简单路径以及图中所有最简单的简单环(环上不存在两个点可以通过环外边直连)
然后在一些数中选出一个子集,使它们与一个给定的数的异或和最大,这就是高斯消元的问题了
利用高斯消元使每一位只存在于最多一个数上 然后贪心求解即可
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define M 50500 using namespace std; typedef long long ll; struct abcd{ int to,next; ll f; }table[200200]; int head[M],tot; int n,m,top; bool v[M]; ll _xor[M],stack[M<<2],ans; void Add(int x,int y,ll z) { table[++tot].to=y; table[tot].f=z; table[tot].next=head[x]; head[x]=tot; } void DFS(int x) { int i; v[x]=true; for(i=head[x];i;i=table[i].next) { if(v[table[i].to]) stack[++top]=_xor[x]^table[i].f^_xor[table[i].to]; else _xor[table[i].to]=_xor[x]^table[i].f,DFS(table[i].to); } } void Gaussian_Elimination() { int i,k=0; ll j; for(j=1ll<<62;j;j>>=1) { for(i=k+1;i<=top;i++) if(stack[i]&j) break; if(i==top+1) continue; swap(stack[++k],stack[i]); for(i=1;i<=top;i++) if( (stack[i]&j) && i!=k ) stack[i]^=stack[k]; } } int main() { int i,x,y; ll z; cin>>n>>m; for(i=1;i<=m;i++) { scanf("%d%d%lld",&x,&y,&z); Add(x,y,z); Add(y,x,z); } DFS(1); Gaussian_Elimination(); ans=_xor[n]; for(i=1;stack[i];i++) if( (ans^stack[i])>ans ) ans^=stack[i]; cout<<ans<<endl; } //lld!!!!
原文地址:http://blog.csdn.net/popoqqq/article/details/39804075