제출 #965073

#제출 시각아이디문제언어결과실행 시간메모리
965073Pannda자매 도시 (APIO20_swap)C++17
43 / 100
2016 ms434224 KiB
#include "swap.h" #include <bits/stdc++.h> using namespace std; const int B = 380; struct DSU { vector<int> f; vector<int> siz; vector<int> deg; vector<bool> ok; DSU() {} DSU(int n) : f(n), siz(n, 1), deg(n, 0), ok(n, false) { iota(f.begin(), f.end(), 0); } int leader(int u) { while (u != f[u]) u = f[u] = f[f[u]]; return u; } bool unionize(int u0, int v0) { int u = leader(u0); int v = leader(v0); if (u == v) { ok[u] = true; return false; } if (siz[u] > siz[v]) swap(u, v); siz[v] += siz[u]; if (++deg[u0] >= 3 || ++deg[v0] >= 3) ok[v] = true; ok[v] = ok[v] | ok[u]; f[u] = v; return true; } bool same(int u, int v) { return leader(u) == leader(v); } bool isOk(int u) { return ok[leader(u)]; } }; struct LiteDSU { vector<int> f; vector<int> siz; vector<bool> ok; LiteDSU(int n) : f(n), siz(n, 1), ok(n, false) { iota(f.begin(), f.end(), 0); } int leader(int u) { while (u != f[u]) u = f[u] = f[f[u]]; return u; } bool unionize(int u, int v) { u = leader(u); v = leader(v); if (u == v) return false; if (siz[u] > siz[v]) swap(u, v); siz[v] += siz[u]; ok[v] = ok[v] | ok[u]; f[u] = v; return true; } bool same(int u, int v) { return leader(u) == leader(v); } bool isOk(int u) { return ok[leader(u)]; } }; int n, m; vector<array<int, 3>> edges; DSU dsu; vector<int> mp; struct Block { int c; vector<int> dom; vector<int> f; vector<int> deg; vector<bool> ok; int leader(int u) { while (u != f[u]) u = f[u] = f[f[u]]; return u; } bool same(int u, int v) { return leader(u) == leader(v); } bool isOk(int u) { return ok[leader(u)]; } Block(int b, DSU &dsu0, DSU &dsu1) { f = dsu0.f; deg = dsu0.deg; ok = dsu0.ok; vector<int> mp(n, -1); for (int i = B * b; i < min(m, B * b + B); i++) { int u = dsu0.leader(edges[i][0]); int v = dsu0.leader(edges[i][1]); if (mp[u] == -1) mp[u] = 0, dom.push_back(u); if (mp[v] == -1) mp[v] = 0, dom.push_back(v); } c = dom.size(); } }; vector<Block> blocks; void init(int N, int M, vector<int> U, vector<int> V, vector<int> W) { n = N; m = M; edges.resize(m); for (int i = 0; i < m; i++) { edges[i] = {U[i], V[i], W[i]}; } sort(edges.begin(), edges.end(), [&](array<int, 3> e0, array<int, 3> e1) { return e0[2] < e1[2]; }); dsu = DSU(n); for (int b = 0; B * b < m; b++) { DSU next_dsu = dsu; for (int i = B * b; i < min(m, B * b + B); i++) { next_dsu.unionize(edges[i][0], edges[i][1]); } blocks.push_back(Block(b, dsu, next_dsu)); dsu = next_dsu; } blocks.emplace_back(100000, dsu, dsu); mp.resize(n, -1); } int getMinimumFuelCapacity(int X, int Y) { if (!dsu.same(X, Y) || !dsu.isOk(X)) return -1; int b = [&]() -> int { int l = 0, r = (int)blocks.size() - 1; while (l < r) { int m = (l + r + 1) >> 1; if (!blocks[m].same(X, Y) || !blocks[m].isOk(X)) { l = m; } else { r = m - 1; } } return l; }(); int label = 0; for (int u : blocks[b].dom) mp[u] = label++; int x = mp[blocks[b].leader(X)]; int y = mp[blocks[b].leader(Y)]; LiteDSU dsu(blocks[b].c); int res = -2; vector<int> defer; for (int u : blocks[b].dom) if (blocks[b].isOk(u)) dsu.ok[mp[u]] = true; for (int i = B * b; i < min(m, B * b + B); i++) { if (!blocks[b + 1].same(X, edges[i][0]) && !blocks[b + 1].same(X, edges[i][1])) continue; int u = mp[blocks[b].leader(edges[i][0])]; int v = mp[blocks[b].leader(edges[i][1])]; if (dsu.same(u, v)) { dsu.ok[dsu.leader(u)] = true; } else { defer.push_back(edges[i][0]); defer.push_back(edges[i][1]); if (++blocks[b].deg[edges[i][0]] >= 3) dsu.ok[dsu.leader(u)] = true; if (++blocks[b].deg[edges[i][1]] >= 3) dsu.ok[dsu.leader(v)] = true; dsu.unionize(u, v); } if (dsu.same(x, y) && dsu.isOk(x)) { res = edges[i][2]; break; } } for (int u : defer) blocks[b].deg[u]--; for (int u : blocks[b].dom) mp[u] = -1; return res; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...