社区讨论
关于此题实现细节的疑问
P8276 [USACO22OPEN] Hoof and Brain P参与者 2已保存回复 5
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 5 条
- 当前快照
- 1 份
- 快照标识符
- @mhk6f2xj
- 此快照首次捕获于
- 2025/11/04 14:16 4 个月前
- 此快照最后确认于
- 2025/11/04 14:16 4 个月前
具体见代码注释。我感觉题解到处都是问题但是它就是过了…想知道为什么。
CPP#include <bits/stdc++.h>
using namespace std;
constexpr int N = 400010;
int n, m, T, q[N], fa[N];
bool vis[N];
unordered_set<int> G[N], s[N];
void toposort() {
int l = 0, r = -1;
for (int i = 1; i <= n; i++)
if (s[i].empty())
q[++r] = i, vis[i] = true;
while (l <= r) {
int u = q[l++];
for (int v : G[u]) {
s[v].erase(u);
if (s[v].empty()) q[++r] = v, vis[v] = true;
}
}
}
int find(int u) {
if (fa[u] != u) fa[u] = find(fa[u]);
return fa[u];
}
bool merge(int& u, int& v) {
u = find(u), v = find(v);
if (u == v) return false;
// if (rand() & 1) swap(u, v);
if (G[u].size() > G[v].size()) swap(u, v);
/*
1. 如果完全不交换,会陷入死循环
2. 如果随机交换,也会陷入死循环
*/
fa[u] = v;
return true;
}
void toposort_ex() {
for (int i = 1; i <= n; i++) fa[i] = i;
int l = 0, r = -1;
for (int i = 1; i <= n; i++)
if (s[i].size() == 1)
q[++r] = i;
while (l <= r) {
int u = q[l++], p = *s[u].begin();
assert(s[u].size() == 1);
if (!merge(u, p)) continue;
for (int v : G[u]) {
//v可能等于u,即在遍历中修改set的值,这可能会死循环,但是实际上没有
G[p].emplace(v);
s[v].erase(u);
s[v].insert(p);//u是p的后继节点时,v=p会为p凭空创造一个自环。自环理论上会影响答案,但是它没对答案造成任何影响。
if (s[v].size() == 1) q[++r] = v;
}
G[u].clear();//此处如果顺便也把出边也删除,同样会WA。但是理论上出边是不是也不需要用了。
}
}
int main() {
freopen("10.in", "r", stdin);
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
cin >> n >> m;
for (int i = 1, u, v; i <= m; i++) {
cin >> u >> v;
G[v].emplace(u); // reverse
s[u].insert(v);
}
toposort();
toposort_ex();
cin >> T;
while (T--) {
int u, v;
cin >> u >> v;
putchar("BH"[!vis[u] && !vis[v] && find(u) != find(v)]);
}
putchar('\n');
return 0;
}
感觉这道题就是在炼仙丹。
回复
共 5 条回复,欢迎继续交流。
正在加载回复...