社区讨论
题解区很离谱
P5163WD与地图参与者 3已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @mkia3iub
- 此快照首次捕获于
- 2026/01/17 20:23 上个月
- 此快照最后确认于
- 2026/01/20 17:20 4 周前
我在讲这道题目的时候,机房大神问我,不是直接并查集就行了吗,我思考着题解的可撤销并查集陷入了沉思。很显然,我的大脑过载了。
但是这样写确实是对的,直接并查集合并就行,没必要撤销,无法理解题解所说的。
核心代码:
CPPvoid solve(int l, int r, vector<int> &v) {
if (v.empty()) return;
if (l == r) {
for (int &x : v) E[x].t = l;
return;
}
int mid = (l + r) >> 1;
vector<int> ll, rr, fl;
init();
for (int &x : v) {
if (E[x].t <= mid) addedge(E[x].u, E[x].v), ll.push_back(x);
else rr.push_back(x);
}
for (int &x : tmp) {
if (!dfn[x]) tarjan(x);
}
vector<pair<int, int> > need; // 需要连起来的边
for (int &x : ll) {
if (block[E[x].u] == block[E[x].v]) fl.push_back(x), need.push_back({E[x].u, E[x].v});
else rr.push_back(x);
}
solve(l, mid, fl);
for (auto &x : need) { // 用并查集的根代表这个强连通分量即可
f[find(x.second)] = find(x.first);
}
for (int &x : rr) {
E[x].u = find(E[x].u);
E[x].v = find(E[x].v);
}
solve(mid + 1, r, rr);
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...