[bzoj 2115]线性基+图论
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2115
给定一个带权无向图,要找出从1到n路径权值异或和最大的那一条的路径异或和。
考虑1到n的任意一条路径,都可以表示为1到n的一条路径,加上图上任意的一些环(1所在的那个连通块)。之所以可以这样,是因为图是连通的,而且无向的,走过去也可以走回来,所以假设当前走到了i号点,我想去走一些环,那么可以i->j->在环j上走一圈->j->i,这条路径上仅仅是异或上了一次环的权值(i->j和j->i的权值被抵消了)。
所以就把所有的环插入线性基就好了。最大值可以从高位到低位贪心来搞。
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=50005; const int maxm=100005*2; vector< pair<int,ll> > G[maxn]; ll a[maxn]; vector<ll> base; void insert(ll x) { for (int i=0;i<base.size();i++) x=min(x,x^base[i]); if (x) base.push_back(x); } void dfs(int u,int fa,ll now) { a[u]=now; for (int i=0;i<G[u].size();i++) { int v=G[u][i].first; ll w=G[u][i].second; if (a[v]==-1) dfs(v,u,now^w); else insert(now^a[v]^w); } } int main() { int n,m; scanf("%d%d",&n,&m); memset(a,-1,sizeof(a)); for (int i=1;i<=m;i++) { int u,v; ll w; scanf("%d%d%lld",&u,&v,&w); G[u].push_back(make_pair(v,w)); G[v].push_back(make_pair(u,w)); } dfs(1,0,0); sort(base.begin(),base.end()); ll ans=a[n]; for (int i=base.size()-1;i>=0;i--) ans=max(ans,ans^base[i]); printf("%lld",ans); return 0; }