QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#111731 | #5670. Group Guests | USP_USP_USP | RE | 24ms | 97372kb | C++23 | 5.4kb | 2023-06-08 05:44:29 | 2023-06-08 05:44:34 |
Judging History
answer
#include <bits/stdc++.h>
using namespace std;
using pii = pair<int, int>;
void merge(pii &x, int y) {
if (x.first > y) x.second = x.first, x.first = y;
else if (x.second > y) x.second = y;
}
int query(const pii &x, int y) {
return y == x.first ? x.second : x.first;
}
#define rep(i, a, b) for (int i = a, I = b; i <= I; ++i)
#define per(i, a, b) for (int i = a, I = b; i >= I; --i)
template<typename T> void down(T &x, T y) { if (x > y) x = y; }
const int N = 2000005;
int n, m, x[N], y[N], par[N];
int dep[N], cnt[N], siz[N], fa[N], cnt1[N], sum[N];
pii mn[N];
bool has_edge[N], has_3[N], sz[N], flag[N], tag[N], vis[N];
vector<int> e[N], e1[N];
vector<pair<int, int>> edges;
int find(int x) {
while (x != par[x]) x = par[x] = par[par[x]];
return x;
}
void merge(int x, int y) {
int u = find(x), v = find(y);
if (u == v) {
sz[u] ^= 1;
} else {
sz[u] ^= sz[v] ^ 1;
par[v] = u;
}
}
// cnt1[u]: grau de backedges
// sum[u]: qtd de backedges no grafo induzido pela subarvore de u sem u
// siz[u]: quantidade de arestas no grafo induzido pela subarvore de u
void dfs(int u) {
mn[u] = pii(1e9, 1e9);
for (auto v : e[u]) {
if (v == fa[u]) continue;
if (!dep[v]) {
++siz[u];
dep[v] = dep[u] + 1;
fa[v] = u;
int tmp = cnt[u];
dfs(v);
has_edge[v] = (cnt[u] > tmp);
siz[u] += siz[v];
sum[u] += sum[v];
merge(mn[u], mn[v].first);
} else {
assert(dep[v] < dep[u]);
++cnt[v];
++siz[v];
merge(mn[u], dep[v]);
sum[u] += 1, sum[v] -= 1;
++cnt1[u], ++cnt1[v];
if (dep[v] == dep[u] - 2) has_3[u] = 1;
edges.push_back({u, v});
}
}
cerr << mn[u].first << ' ' << mn[u].second << '\n';
}
bool dfs1(int u) {
for (auto v : e[u]) {
if (fa[v] != u) continue;
if (dfs1(v)) return 1;
}
if (has_3[u]) {
int v = fa[u], w = fa[v];
bool has_uv = has_edge[u];
bool has_uw = (query(mn[u], dep[w]) <= dep[w]);
bool has_vw = (query(mn[v], mn[u].first) <= dep[w]);
int cnt = has_uv + has_uw + has_vw;
if (cnt >= 2) return 1;
bool sz_u = siz[u] & 1;
bool sz_v = (siz[v] - siz[u] - 1) & 1;
bool sz_w = (siz[v] + 1) & 1; // siz[root] - siz[v] - 2
// sizes of each part (assuming it's disconnected)
if (cnt == 0 && !sz_u && !sz_v && !sz_w) return 1;
if (has_uv && !sz_w) return 1;
if (has_uw && !sz_v) return 1;
if (has_vw && !sz_u) return 1;
}
for (auto v : e[u]) if (fa[v] != u && v != fa[u]) vis[v] = 1;
bool tmp = 0;
for (auto v : e[u]) {
if (fa[v] == u || v == fa[u]) continue;
int d = dep[v];
if (d < dep[u]) {
int w = fa[v];
if (!w || !vis[w]) continue;
if (sum[v] > 1) {
tmp = 1;
break;
}
bool sz_v = (siz[v] - 1) & 1;
if (!sz_v) {
tmp = 1;
break;
}
} else {
int w = fa[v];
if (!vis[w]) continue;
if (sum[v] > 1) {
tmp = 1;
break;
}
bool sz_v = siz[v] & 1;
if (!sz_v) {
tmp = 1;
break;
}
}
}
for (auto v : e[u]) if (fa[v] != u && v != fa[u]) vis[v] = 0;
return tmp;
}
bool dfs2(int u) {
int mx = cnt1[u];
bool sz = (siz[u] ^ sum[u]) & 1; // all - siz[u] - 1 - sum1[u]
// cerr << "u = " << u << ", siz = " << siz[u] << ", sum1 = " << sum1[u] << "\n";
for (auto v : e[u]) {
if (fa[v] != u) continue;
if (dfs2(v)) return 1;
if (mn[v].first < dep[u]) {
sz ^= (sum[v] ^ siz[v]) & 1;
// cerr << "? " << u << " " << v << " " << ((sum[v] ^ siz[v]) & 1) << "\n";
++mx;
} else {
mx += !(siz[v] & 1);
}
}
// cerr << "u = " << u << ", siz = " << siz[u] << ", sz = " << sz << "\n";
if (!sz && fa[u]) ++mx;
return mx >= 3;
}
void debug(int u) {
// for (auto v : e[u]) {
// if (dep[v] > dep[u]) cout << u << " " << v << "\n";
// if (fa[v] == u) debug(v);
// }
}
int main() {
// freopen("1.in", "r", stdin);
// freopen("1.out", "w", stdout);
ios::sync_with_stdio(0), cin.tie(0);
cin >> m >> n;
rep(i, 1, m) {
cin >> x[i] >> y[i];
e[x[i]].push_back(y[i]);
e[y[i]].push_back(x[i]);
}
rep(i, 1, n) par[i] = i;
rep(i, 1, m) merge(x[i], y[i]);
rep(i, 1, n) {
if (find(i) != i || !sz[i]) continue;
dep[i] = 1, dfs(i);
flag[i] = dfs1(i);
}
for (auto it : edges) {
int x = it.first, y = it.second;
if (cnt1[x] < cnt1[y] && (cnt1[x] == cnt1[y] && x < y)) swap(x, y);
e1[x].push_back(y);
}
rep(i, 1, n) {
if (flag[find(i)]) continue;
for (auto j : e1[i]) for (auto k : e1[j]) tag[k] = 1;
bool cur = 0;
for (auto j : e1[i]) cur |= tag[j];
flag[find(i)] |= cur;
for (auto j : e1[i]) for (auto k : e1[j]) tag[k] = 0;
}
int ans1 = 0, ans2 = 0;
rep(i, 1, n) {
if (find(i) != i || !sz[i] || flag[i]) continue;
++(dfs2(i) ? ans2 : ans1);
debug(i);
}
cout << ans1 << " " << ans2 << "\n";
return 0;
}
详细
Test #1:
score: 100
Accepted
time: 12ms
memory: 97264kb
input:
2 4 1 2 3 4
output:
2 0
result:
ok single line: '2 0'
Test #2:
score: 0
Accepted
time: 24ms
memory: 97372kb
input:
2 3 1 2 3 1
output:
0 0
result:
ok single line: '0 0'
Test #3:
score: -100
Dangerous Syscalls
input:
5 5 1 2 2 3 2 4 5 2 5 4