「WC2011」「bzoj2115」最大XOR和路径 - 找环+线性基 | Bill Yang's Blog

「WC2011」「bzoj2115」最大XOR和路径 - 找环+线性基

题目大意

    给出一个边权非负的无向连通图,求一条从$1\rightarrow n$的路径,使得路径边权的$xor$和最大。
    若一条边在路径中多次出现,权值也要被累加相应多次。


题目分析

这道题看起来比较NP,但是经过仔细分析后就变成了水题。

考虑,这条路径只可能是一条链与多个环拼接而成的,如图。

如果我们想要获得一个环上的所有权值,就必定要经过通向这个环的边。
但如果我们不想要这些边怎么办?
没关系,我们再从这些边走回来就可以了,这样边的权值就被异或抵消了。

这样,我们要求的异或和就变成了若干个独立的环与一条$1\rightarrow n$的链的异或和。

先考虑环。
不难想到一种暴力思路,求出原图中的所有环,然后构造线性基。
然而找出原图中所有环的时间复杂度是指数级的。

不难发现,若一个环异或另一个环就可以得到另一个环。
故,我们只需要求出部分环即可。
这里我们可以使用Dfs判断返祖边来得到一个环。

接下来我们来考虑链。
直接说结论:随意找一条$1\rightarrow n$的路径,让根据环构造的线性基从大到小与路径权值异或取最大值即可。

为什么这是对的呢?

考虑若路径有多条,任意一条一定能够表示为另一条路径与一个环异或,因为已经对环构造了线性基,故任意求一条即可。


代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include<algorithm>
#include<iostream>
#include<iomanip>
#include<cstring>
#include<cstdlib>
#include<climits>
#include<vector>
#include<cstdio>
#include<cmath>
#include<queue>
using namespace std;
typedef long long LL;
inline const LL Get_Int() {
LL num=0,bj=1;
char x=getchar();
while(x<'0'||x>'9') {
if(x=='-')bj=-1;
x=getchar();
}
while(x>='0'&&x<='9') {
num=num*10+x-'0';
x=getchar();
}
return num*bj;
}
const int maxn=200005,MAX_BASE=60;
struct Linear_Bases {
LL b[MAX_BASE+5];
void build(vector<LL> a) {
for(LL num:a)
for(int j=MAX_BASE; j>=0; j--)
if(num>>j&1) {
if(b[j]) { //该位存在基
num^=b[j];
continue;
}
b[j]=num;
for(int k=j-1; k>=0; k--)if(b[j]>>k&1)b[j]^=b[k];
for(int k=j+1; k<=MAX_BASE; k++)if(b[k]>>j&1)b[k]^=b[j];
break;
}
}
} lb;
struct Edge {
int from,to;
LL dist;
Edge(int x=0,int y=0,LL v=0):from(x),to(y),dist(v) {}
};
vector<Edge>edges[maxn];
vector<LL>a;
int n,m,vst[maxn];
LL Dist[maxn];
void AddEdge(int x,int y,LL v) {
edges[x].push_back(Edge(x,y,v));
}
void Dfs(int Now) {
vst[Now]=1;
for(Edge& e:edges[Now]) {
int Next=e.to;
LL dist=e.dist;
if(!vst[Next]) {
Dist[Next]=Dist[Now]^dist;
Dfs(Next);
} else a.push_back(Dist[Now]^Dist[Next]^dist);
}
}
int main() {
n=Get_Int();
m=Get_Int();
for(int i=1; i<=m; i++) {
int x=Get_Int(),y=Get_Int();
LL v=Get_Int();
AddEdge(x,y,v);
AddEdge(y,x,v);
}
Dfs(1);
lb.build(a);
LL ans=Dist[n];
for(int i=MAX_BASE; i>=0; i--)ans=max(ans,ans^lb.b[i]);
printf("%lld\n",ans);
return 0;
}
0%