P3366 【模板】最小生成树
这个算法就是考虑每一次合并 n n n 个联通块,变成 n 2 \frac{n}{2} 2n 个。所以总共合并的次数是 log 2 n \log_2 n log2n 次。
我们还是使用并查集来维护每一个联通块,这个算法的好处就是因为其合并次数是 log n \log n logn 级别的,所以我们可以在里面进行 O ( n ) O(n) O(n) 的处理。来处理一些不能直接进行最小生成树的情况。
比如说要维护两点 & \& & 值为 0 0 0 的图。我们直接使用 p r i m \tt prim prim 复杂度会直接爆炸。但是我们用 B o r u v k a \tt Boruvka Boruvka 可以每一次 O ( n ) O(n) O(n) 级别处理各种联通块的信息,然后进行生成树。
对于模板题具体来说,我们对于每一个联通块维护一个最小的边权,边的另外一头是与其所属联通块不同的点。
这边注意每一次操作应该考虑的是所属联通块,然后这边有一个很好的性质 可能也没有那么有性质。
在进行合并联通块之前,联通块的根是不会变的 \color{red}\tt \text{在进行合并联通块之前,联通块的根是不会变的} 在进行合并联通块之前,联通块的根是不会变的。
这样我们可以直接在预处理的时候存储每个集合的根,看起来这个性质不起眼,但是在题目中可以方便许多。
#include <bits/stdc++.h>
using namespace std;
//#define Fread
//#define Getmod
#ifdef Fread
char buf[1 << 21], *iS, *iT;