其他分享
首页 > 其他分享> > [APIO2019]桥梁

[APIO2019]桥梁

作者:互联网

  • 给定边带权的无向图 \((V,E)\)。\(q\) 次操作,改变一条边的权值或者询问从 \(s_i\) 出发只走权值大于等于 \(w_i\) 的边能够到达的点数。
  • \(|V| \leq 5 \times 10^4, |E|, q \leq 10^5\) 。

分别考虑涉及修改和不涉及修改的边:

将操作分块,设块大小为 \(S\),第一部分变为 \(O(|E|\log |E| + S \log S)\),第二部分变为 \(O(S^2)\)。

总复杂度 \(O(\frac qS|E|\log|E|+q\log S + qS)\),基本不等式大概算一下块大小,卡常。

#include <bits/stdc++.h>
#define dbg(...) std::cerr << "\033[32;1m", fprintf(stderr, __VA_ARGS__), std::cerr << "\033[0m"
template <class T, class U>
inline bool smin(T &x, const U &y) { return y < x ? x = y, 1 : 0; }
template <class T, class U>
inline bool smax(T &x, const U &y) { return x < y ? x = y, 1 : 0; }
using LL = long long;
using PII = std::pair<int, int>;

constexpr int N(5e4 + 5), S(500);
int fa[N], siz[N];
int find(int x) {
  while (fa[x] != x) x = fa[x];
  return x;
}
int main() {
  std::ios::sync_with_stdio(false);
  std::cin.tie(nullptr);
  int n, m, q;
  std::cin >> n >> m;
  std::vector<std::array<int, 3>> e(m);
  for (auto &[x, y, z] : e) std::cin >> x >> y >> z;
  std::vector<int> eq(m);
  std::iota(eq.begin(), eq.end(), 0);
  auto cmp_edge = [&](int i, int j) { return e[i][2] > e[j][2]; };
  std::sort(eq.begin(), eq.end(), cmp_edge);
  std::cin >> q;
  for (int i = 0; i < q; i += S) {
    std::vector<std::array<int, 3>> a, b;
    std::vector<char> vis(m);
    for (int j = 0; j < S && i + j < q; j++) {
      int t, x, y;
      std::cin >> t >> x >> y;
      if (t == 1) {
        vis[--x] = 1;
        a.push_back({ j, x, y });
      } else {
        b.push_back({ j, x, y });
      }
      (t == 1 ? a : b).push_back({ j, x, y });
    }
    std::sort(b.begin(), b.end(), [](const auto &x, const auto &y) { return x[2] > y[2]; });
    std::vector<int> c, d, ans(a.size() + b.size());
    for (int j = 0; j < m; j++) {
      if (!vis[eq[j]]) {
        c.push_back(eq[j]);
      } else {
        d.push_back(eq[j]);
      }
    }
    std::iota(fa, fa + n + 1, 0);
    std::fill(siz, siz + n + 1, 1);
    auto p = c.begin();
    for (auto &[t, s, w] : b) {
      for (; p != c.end() && e[*p][2] >= w; p++) {
        int x = find(e[*p][0]), y = find(e[*p][1]);
        if (x == y) continue;
        if (siz[x] > siz[y]) std::swap(x, y);
        fa[x] = y, siz[y] += siz[x];
      }
      
      std::vector<int> pre(d.size());
      for (int j = 0; j < d.size(); j++) {
        pre[j] = e[d[j]][2];
      }
      for (auto &[tt, x, y] : a) {
        if (tt > t) continue;
        e[x][2] = y;
      }
      std::vector<std::array<int, 3>> v;
      for (int j : d) {
        if (e[j][2] >= w) {
          int x = find(e[j][0]), y = find(e[j][1]);
          if (x == y) continue;
          if (siz[x] > siz[y]) std::swap(x, y);
          v.push_back({ x, y, fa[x] });
          fa[x] = y, siz[y] += siz[x];
        }
      }
      ans[t] = siz[find(s)];
      while (!v.empty()) {
        auto &[x, y, z] = v.back();
        fa[x] = z, siz[y] -= siz[x];
        v.pop_back();
      }
      for (int j = 0; j < d.size(); j++) {
        e[d[j]][2] = pre[j];
      }
    }
    for (int i : ans) if (i) std::cout << i << "\n";
    for (auto &[t, x, y] : a) e[x][2] = y;
    std::sort(d.begin(), d.end(), cmp_edge);
    std::merge(c.begin(), c.end(), d.begin(), d.end(), eq.begin(), cmp_edge);
  }
  return 0;
}

标签:std,APIO2019,int,siz,桥梁,fa,auto,eq
来源: https://www.cnblogs.com/HolyK/p/14332957.html