QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#562904 | #9102. Zayin and Elements | ucup-team004 | AC ✓ | 1ms | 3704kb | C++20 | 5.8kb | 2024-09-13 22:42:36 | 2024-09-13 22:42:37 |
Judging History
answer
#include <bits/stdc++.h>
using i64 = long long;
using u64 = unsigned long long;
using u32 = unsigned;
constexpr int inf = 1E9;
struct Graph {
int n;
std::vector<std::vector<int>> e;
Graph(int n) : n(n), e(n) {}
void addEdge(int u, int v) {
e[u].push_back(v);
e[v].push_back(u);
}
std::vector<int> findMatching(int m, const auto &init) {
std::vector<int> match(n, -1), vis(n), link(n), f(n), dep(n);
for (auto [x, y] : init) {
match[x] = y;
match[y] = x;
}
// disjoint set union
auto find = [&](int u) {
while (f[u] != u)
u = f[u] = f[f[u]];
return u;
};
auto lca = [&](int u, int v) {
u = find(u);
v = find(v);
while (u != v) {
if (dep[u] < dep[v])
std::swap(u, v);
u = find(link[match[u]]);
}
return u;
};
std::queue<int> que;
auto blossom = [&](int u, int v, int p) {
while (find(u) != p) {
link[u] = v;
v = match[u];
if (vis[v] == 0) {
vis[v] = 1;
que.push(v);
}
f[u] = f[v] = p;
u = link[v];
}
};
// find an augmenting path starting from u and augment (if exist)
auto augment = [&](int u) {
while (!que.empty())
que.pop();
std::iota(f.begin(), f.end(), 0);
// vis = 0 corresponds to inner vertices, vis = 1 corresponds to outer vertices
std::fill(vis.begin(), vis.end(), -1);
que.push(u);
vis[u] = 1;
dep[u] = 0;
int y = -1;
while (!que.empty()){
int u = que.front();
que.pop();
if (u >= m) {
y = u;
}
for (auto v : e[u]) {
if (vis[v] == -1) {
vis[v] = 0;
link[v] = u;
dep[v] = dep[u] + 1;
// found an augmenting path
if (match[v] == -1) {
for (int x = v, y = u, temp; y != -1; x = temp, y = x == -1 ? -1 : link[x]) {
temp = match[y];
match[x] = y;
match[y] = x;
}
return;
}
vis[match[v]] = 1;
dep[match[v]] = dep[u] + 2;
que.push(match[v]);
} else if (vis[v] == 1 && find(v) != find(u)) {
// found a blossom
int p = lca(u, v);
blossom(u, v, p);
blossom(v, u, p);
}
}
}
if (y != -1) {
for (int x = -1, temp; y != -1; x = temp, y = x == -1 ? -1 : link[x]) {
temp = match[y];
if (x != -1) {
match[x] = y;
}
match[y] = x;
}
}
};
// find a maximal matching greedily (decrease constant)
// auto greedy = [&]() {
// for (int u = 0; u < n; ++u) {
// if (match[u] != -1)
// continue;
// for (auto v : e[u]) {
// if (match[v] == -1) {
// match[u] = v;
// match[v] = u;
// break;
// }
// }
// }
// };
// greedy();
for (int u = 0; u < m; ++u)
if (match[u] == -1)
augment(u);
return match;
}
};
void solve() {
int n, m;
std::cin >> n >> m;
int tot = n;
std::vector<int> a(m), b(m), c(m);
std::vector<std::vector<int>> adj(m);
for (int i = 0; i < m; i++) {
std::cin >> a[i] >> b[i] >> c[i];
tot += a[i] + 2 * b[i] + 2 * c[i];
int t;
std::cin >> t;
adj[i].resize(t);
for (int j = 0; j < t; j++) {
std::cin >> adj[i][j];
adj[i][j]--;
}
}
Graph g(tot);
std::vector<std::array<int, 2>> init;
int cur = n;
for (int i = 0; i < m; i++) {
for (int j = 0; j < a[i]; j++) {
for (auto v : adj[i]) {
g.addEdge(v, cur);
}
cur++;
}
for (int j = 0; j < b[i]; j++) {
for (auto v : adj[i]) {
g.addEdge(v, cur);
g.addEdge(v, cur + 1);
}
init.push_back({cur, cur + 1});
g.addEdge(cur, cur + 1);
cur += 2;
}
for (int j = 0; j < c[i]; j++) {
for (auto v : adj[i]) {
g.addEdge(v, cur);
}
init.push_back({cur, cur + 1});
g.addEdge(cur, cur + 1);
cur += 2;
}
}
auto match = g.findMatching(n, init);
if (std::find(match.begin(), match.begin() + n, -1) != match.begin() + n) {
std::cout << -1 << "\n";
return;
}
int ans = 0;
for (int i = 0; i < tot; i++) {
ans += (match[i] > i);
}
ans -= n;
std::cout << ans << "\n";
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
int t;
std::cin >> t;
while (t--) {
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 0ms
memory: 3548kb
input:
2 5 2 2 3 1 2 3 1 1 1 1 3 4 5 2 5 2 2 3 1 1 3 1 0 1 2 1 2
output:
5 -1
result:
ok 2 lines
Test #2:
score: 0
Accepted
time: 1ms
memory: 3704kb
input:
5 9 10 0 0 10 2 3 8 0 0 10 2 4 6 0 8 2 2 2 4 0 0 10 3 1 3 8 0 4 6 2 2 3 0 8 2 3 2 6 7 0 9 1 2 1 7 0 2 8 3 1 4 9 0 7 3 1 5 0 0 10 3 5 6 9 3 10 0 9 1 1 2 0 5 5 1 1 0 1 9 1 1 0 7 3 1 1 0 7 3 0 0 0 10 0 0 6 4 1 3 0 9 1 0 0 7 3 0 0 9 1 1 2 90 20 0 6 4 12 1 4 5 22 32 64 66 67 73 87 88 89 0 1 9 12 3 8 21 3...
output:
94 97 155 151 152
result:
ok 5 lines