卧薪尝胆,厚积薄发。
Shortest Path Problem
Date: Tue Nov 06 11:01:44 CST 2018 In Category: NoCategory

Description:

求一条从 $1$ 到 $n$ 异或和最小的路径。
$1\leqslant n\leqslant 10^5$

Solution:

和 $WC$ 最大 $Xor$ 路径一样的题,但是有一个更理性的找环方法,就是先随便找一个生成树,然后再把所有非树边构成的环加进线性基里,因为 $LCA$ 之上的部分会被异或消掉,所以不用链剖。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
int n,m;
#define MAXN 100010
struct edges
{
int u,v,w;
}es[MAXN];
bool tag[MAXN];
int f[MAXN];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
struct LinearBase
{
int d[29];
void insert(int x)
{
for(int i = 28;i >= 0;--i)
{
if(x & (1 << i))
{
if(d[i] == 0)
{
d[i] = x;
break;
}
else
{
x ^= d[i];
}
}
}
return;
}
int query(int x)
{
for(int i = 28;i >= 0;--i)
{
if((x ^ d[i]) < x)
{
x ^= d[i];
}
}
return x;
}
}s;
struct edge
{
int to,nxt,v;
}e[MAXN << 1];
int edgenum = 0;
int lin[MAXN] = {0};
void add(int a,int b,int c)
{
e[++edgenum] = (edge){b,lin[a],c};lin[a] = edgenum;
e[++edgenum] = (edge){a,lin[b],c};lin[b] = edgenum;
return;
}
int val[MAXN];
bool v[MAXN];
void dfs(int k)
{
v[k] = true;
for(int i = lin[k];i != 0;i = e[i].nxt)
{
if(v[e[i].to])continue;
val[e[i].to] = val[k] ^ e[i].v;
dfs(e[i].to);
}
return;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;++i)
{
scanf("%d%d%d",&es[i].u,&es[i].v,&es[i].w);
}
for(int i = 1;i <= n;++i)f[i] = i;
for(int i = 1;i <= m;++i)
{
int p = find(es[i].u),q = find(es[i].v);
if(p == q)continue;
add(es[i].u,es[i].v,es[i].w);
f[p] = q;
}
dfs(1);
for(int i = 1;i <= m;++i)
{
s.insert(val[es[i].u] ^ val[es[i].v] ^ es[i].w);
}
cout << s.query(val[1] ^ val[n]) << endl;
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡