跳转至

并查集

线下模版

普通并查集

vector<int> fa, sz;

void init(int n) {
  for (int i = 1; i <= n; i ++) {
    fa[i] = i;
    sz[i] = 1;
  }
}

int find(int u) {
  if (fa[u] == u) return u;
  return fa[u] = find(fa[u]);
}

void unite(int u, int v) {
  int from = find(u), to = find(v);
  if (from == to) return;
  if (sz[from] > sz[to]) swap(from, to);
  fa[from] = to;
  sz[to] += sz[from];
}

bool is_united(int u, int v) {
  return find(u) == find(v);
}

vector<vector<int>> group() {

}

带边权并查集

核心思想是:每一个节点维护一个到父节点的权值,路径压缩时沿途累加权值 weight[u] = val[u] - val[root] val[u] = val[root] + weight[u]

vector<int> fa, sz, weight;

void init(int n) {
  fa.resize(n + 1);
  sz.assigin(n + 1, 1);
  weight.resize(n + 1, 0);
  iota(fa.begin(), fa.end(), 0);
}

int find(int u) {
  if (fa[u] == u) return u;
  int anc = find(fa[u]);
  weight[u] += weight[fa[u]];
  return fa[u] = anc;
}

bool unite(int u, int v, int w) { // u -> v
  int from = find(u), to = find(v);
  if (from == to) return weight[u] - weight[v] == w;
  int exp_to = to;
  if (sz[from] > sz[to]) {
    swap(from, to);
  }
  // val[u] - val[from] = weight[u]
  // val[v] - val[to] = weight[v]
  // val[u] - val[v] = w
  // val[from] - val[to] = ? = weight[from]
  sz[to] += sz[from];
  if (exp_to == to) {
    weight[from] = weight[v] - weight[u] + w;
  } else {
    weight[from] = weight[u] - weight[v] - w;
  }
  fa[from] = to;
  return 1;
}

bool is_united(int u, int v) {
  return find(u) == find(v);
}

其他类型并查集线下模版还没总结完