洛谷 P8026 [ONTAK2015] Bajtocja
简要题意
有
数据范围:
题解
首先图连通性可以考虑一个启发式合并的思路,也就是可以暴力修改小的那个集合的所属信息。现在的问题是你没法判定有多少个点和当前点联通,遍历所有集合是不现实的。考虑进行一个集合哈希,给所有点在所有图中都附上随机权值,然后一个点的权值通过他在这些图的并查集里的代表元的权值运算得到,这样如果两个点权值一样,它们大概率在所有图中代表元都相同,也就是都联通。由于你只有 5000 个点,单哈希即可。
代码
// Author: kyEEcccccc #include <bits/stdc++.h> using namespace std; using LL = long long; using ULL = unsigned long long; #define F(i, l, r) for (int i = (l); i <= (r); ++i) #define FF(i, r, l) for (int i = (r); i >= (l); --i) #define MAX(a, b) ((a) = max(a, b)) #define MIN(a, b) ((a) = min(a, b)) #define SZ(a) ((int)((a).size()) - 1) int n, m, d; mt19937_64 ran(chrono::system_clock::now().time_since_epoch().count()); ULL hsh[5005], val[205][5005]; vector<int> to[205][5005]; unordered_map<ULL, int> tot; struct Dsu { int a[5005], sz[5005]; void init(int n) { iota(a + 1, a + n + 1, 1); fill(sz + 1, sz + n + 1, 1); } int get_anc(int x) { return x == a[x] ? x : (a[x] = get_anc(a[x])); } int get_size(int x) { return sz[get_anc(x)]; } bool is_same(int x, int y) { return get_anc(x) == get_anc(y); } bool mer(int x, int y) { x = get_anc(x), y = get_anc(y); if (x == y) return 0; a[y] = x; sz[x] += sz[y]; sz[y] = 0; return 1; } } dsu[205]; int ans; void calc(int k, int u, int par, ULL delt) { ans -= 2 * tot[hsh[u]]; --tot[hsh[u]]; // cerr << hsh[u] << '\n'; hsh[u] += delt; // cerr << hsh[u] << '\n'; ++tot[hsh[u]]; ans += 2 * tot[hsh[u]]; for (int v : to[k][u]) if (v != par) calc(k, v, u, delt); } signed main(void) { // freopen(".in", "r", stdin); // freopen(".out", "w", stdout); ios::sync_with_stdio(0), cin.tie(nullptr); cin >> d >> n >> m; uniform_int_distribution<ULL> gen_val(1, numeric_limits<ULL>::max()); F(i, 1, d) F(j, 1, n) val[i][j] = gen_val(ran), hsh[j] += val[i][j]; F(i, 1, n) tot[hsh[i]] = 1; F(i, 1, d) dsu[i].init(n); ans = n; F(i, 1, m) { int a, b, k; cin >> a >> b >> k; if (dsu[k].is_same(a, b)) { cout << ans << '\n'; continue; } if (dsu[k].get_size(a) > dsu[k].get_size(b)) swap(a, b); calc(k, a, 0, val[k][dsu[k].get_anc(b)] - val[k][dsu[k].get_anc(a)]); dsu[k].mer(b, a); to[k][a].push_back(b); to[k][b].push_back(a); cout << ans << '\n'; } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!