关于 Boruvka 算法
  • 板块CF888G Xor-MST
  • 楼主yzq_yzq
  • 当前回复0
  • 已保存回复0
  • 发布时间2024/9/4 20:06
  • 上次更新2024/9/4 22:43:03
查看原帖
关于 Boruvka 算法
560006
yzq_yzq楼主2024/9/4 20:06

写的是较为好写的分治写法,求出 nlog⁡nn \log n 条边后跑 Kruscal ,有没有大佬能解释一下这个的正确性,顺便问下为什么我 aa 数组没排序的过不去。

#include <bits/stdc++.h>
#define rep(i, x, y) for (int i = x; i <= y; ++i)
#define drep(i, x, y) for (int i = x; i >= y; --i)
#define ll long long
#define pb push_back
#define IOS ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
using namespace std;
const int N = 200020;
struct edge {
	int u, v, w;
} E[N * 40];
int n, cnt, idx, fa[N], a[N], t[N * 30][2], id[N * 30];
int find(int x) {
	if(fa[x] == x) return x;
	return fa[x] = find(fa[x]);
}
inline void Up(int &p) {
	if(!p) {
		p = ++idx;
		t[p][0] = t[p][1] = 0;
	}
}
inline void clear() {
	idx = 1;
	t[1][0] = t[1][1] = 0;
}
inline void ins(int x, int i) {
	int p = 1;
	drep(i, 29, 0) {
		int c = (x >> i) & 1;
		Up(t[p][c]);
		p = t[p][c];
	}
	id[p] = i;
}
inline int qry(int x) {
	int p = 1;
	drep(i, 29, 0) {
		int c = (x >> i) & 1;
		if(t[p][c]) p = t[p][c];
		else p = t[p][c ^ 1];
	}
	return id[p];
}
void solve(int l, int r) {
	if(l == r) return;
	int mid = (l + r) >> 1;
	solve(l, mid), solve(mid + 1, r);
	clear();
	rep(i, l, mid) ins(a[i], i);
	rep(i, mid + 1, r) {
		int j = qry(a[i]); assert(j);
		E[++cnt] = {i, j, a[i] ^ a[j]};
	}
	clear();
	rep(i, mid + 1, r) ins(a[i], i);
	rep(i, l, mid) {
		int j = qry(a[i]); assert(j);
		E[++cnt] = {i, j, a[i] ^ a[j]};
	}
}
bool merge(int x, int y) {
	x = find(x), y = find(y);
	if(x == y) return 0;
	fa[x] = y; return 1;
}
int main() {
	IOS;
	cin >> n; rep(i, 1, n) cin >> a[i];
	sort(a + 1, a + 1 + n);
	ll res = 0; rep(i, 1, n) fa[i] = i; solve(1, n);
	sort(E + 1, E + 1 + cnt, [&](edge x, edge y) { return x.w < y.w; });
	rep(i, 1, cnt) if(merge(E[i].u, E[i].v)) res += E[i].w;
	cout << res << '\n';
	return 0;
}
2024/9/4 20:06
加载中...