把淘汰赛问题转换为一棵生成树,每一条边相当于一个二选一淘汰的过程。

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
// ==============================
// author: memset0
// website: https://memset0.cn
// ==============================
#include <bits/stdc++.h>
#define ll long long
using namespace std;

ll read() {
ll x = 0; bool m = 0; char c = getchar();
while (!isdigit(c) && c != '-') c = getchar();
if (c == '-') m = 1, c = getchar();
while (isdigit(c)) x = x * 10 + c - '0', c = getchar();
if (m) return -x; else return x;
}

const int maxn = 2010;

ll n, cnt, ans;
ll a[maxn], fa[maxn];

struct edge {
ll u, v, w;
edge () {}
edge (ll a, ll b, ll c) { u = a, v = b, w = c; }
} e[2000010];

bool operator < (edge a, edge b) {
return a.w > b.w;
}

ll find(ll x) {
if (fa[x] == x) return x;
return fa[x] = find(fa[x]);
}

int main() {

n = read();
for (int i = 1; i <= n; i++)
a[i] = read();

for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
e[++cnt] = edge(i, j, a[i] ^ a[j]);

sort(e + 1, e + cnt + 1);
for (int i = 1; i <= n; i++)
fa[i] = i;

for (int i = 1; i <= cnt; i++)
if (find(e[i].u) != find(e[i].v)) {
fa[find(e[i].u)] = find(e[i].v);
ans += e[i].w;
}
printf("%lld\n", ans);

return 0;
}