BZOJ传送门
洛谷传送门
解析:
额这道题可能是
W
C
WC
WC场上的签到题。
但不知道为什么被标成了黑题。。。
感觉不是一般
W
C
WC
WC的水平啊。
太简单了一点吧。。。
思路:
我们发现,重复的走过同一条路径对答案是没有任何贡献的。异或的自反性使得这道题十分的奇妙。
我们随便记录每个点到1的任意一条路径的前缀异或和。发现当我们随便选出一条从1到 n n n的路径之后,只有与1或 n n n联通的环能够更新答案。
并且这个更新答案是任意更新。
显而易见,线性基。
具体做法就是利用 D F S DFS DFS或者 B F S BFS BFS,处理出所有点到1的任意路径,同时找出所有的环,并将环扔进线性基里面。如果把线性基的构建当做常数时间的话,那么这里的的复杂度就只有 O ( V + E ) O(V+E) O(V+E)。
我们已经处理出了所有能够用于更新答案的环,那么我们取出任意一条1到 n n n的路径,丢到线性基里面,算出最大的答案。环的权值可以用差分来计算。
notes:
顺便提一下,为什么能够随便取路径。
首先,如果这是唯一路径,自然不用多说。
如果有多条路径,则必然存在环。
那环已经被丢到线性基里面了啊。
我们在线性基里面异或就可以取出最优的答案了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
ll getint(){
re ll num;
re char c;
while(!isdigit(c=gc()));
num=c^48;
while(isdigit(c=gc()))num=(num<<1)+(num<<3)+(c^48);
return num;
}
ll b[64];
inline
void insert(ll a){
if(a)
for(int re i=62;~i;--i){
if(a&(1ll<<i))
if(!b[i]){
b[i]=a;
break;
}
else a^=b[i];
}
}
inline ll query(ll a){
for(int re i=62;~i;--i)
if((a^b[i])>a)a^=b[i];
return a;
}
cs int N=50001,M=100003;
int last[N],nxt[M<<1],to[M<<1],ecnt;
ll w[M<<1];
inline
void addedge(int u,int v,ll val){
nxt[++ecnt]=last[u],last[u]=ecnt,to[ecnt]=v,w[ecnt]=val;
nxt[++ecnt]=last[v],last[v]=ecnt,to[ecnt]=u,w[ecnt]=val;
}
ll dist[N];
bool vis[N];
int n,m;
inline
void dfs(int u,ll res){
vis[u]=true;
dist[u]=res;
for(int re e=last[u],v=to[e];e;v=to[e=nxt[e]])
if(!vis[v])dfs(v,res^w[e]);
else insert(res^w[e]^dist[v]);
}
signed main(){
n=getint(),m=getint();
for(int re i=1;i<=m;++i){
int u=getint(),v=getint();
ll val=getint();
addedge(u,v,val);
}
dfs(1,0);
cout<<query(dist[n])<<endl;
return 0;
}