diff --git "a/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/03A - \345\233\276\350\256\272.md" "b/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/03A - \345\233\276\350\256\272.md" index a1eefa8..6baede7 100644 --- "a/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/03A - \345\233\276\350\256\272.md" +++ "b/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/03A - \345\233\276\350\256\272.md" @@ -431,31 +431,31 @@ struct SCC { ```c++ struct EDCC { - int n, now, cnt; - vector> ver; + int n, m, now, cnt; + vector>> ver; vector dfn, low, col, S; - set> bridge; + set> bridge, direct; // 如果不需要,删除这一部分可以得到一些时间上的优化 - EDCC(int n) : n(n), ver(n + 1), low(n + 1) { - dfn.resize(n + 1, -1); - col.resize(n + 1, -1); - now = cnt = 0; + EDCC(int n) : n(n), low(n + 1), ver(n + 1), dfn(n + 1), col(n + 1) { + m = now = cnt = 0; } void add(int x, int y) { // 和 scc 相比多了一条连边 - ver[x].push_back(y); - ver[y].push_back(x); + ver[x].push_back({y, m}); + ver[y].push_back({x, m++}); } - void tarjan(int x, int fa) { // 和 scc 相比多了一个 fa - dfn[x] = low[x] = now++; + void tarjan(int x, int fa) { + dfn[x] = low[x] = ++now; S.push_back(x); - for (auto y : ver[x]) { - if (y == fa) continue; - if (dfn[y] == -1) { - bridge.insert({x, y}); // 储存割边 - tarjan(y, x); + for (auto &[y, id] : ver[x]) { + if (!dfn[y]) { + direct.insert({x, y}); + tarjan(y, id); low[x] = min(low[x], low[y]); - } else if (col[y] == -1 && dfn[y] < dfn[x]) { - bridge.insert({x, y}); + if (dfn[x] < low[y]) { + bridge.insert({x, y}); + } + } else if (id != fa && dfn[y] < dfn[x]) { + direct.insert({x, y}); low[x] = min(low[x], dfn[y]); } } @@ -469,18 +469,22 @@ struct EDCC { } while (pre != x); } } - auto work() { // [cnt 新图的顶点数量, bridge 全部割边] + auto work() { for (int i = 1; i <= n; i++) { // 避免图不连通 - if (dfn[i] == -1) { + if (!dfn[i]) { tarjan(i, 0); } } - - vector siz(cnt + 1); // siz 每个边双中点的数量 - vector> adj(cnt + 1); // adj 新图 + /** + * @param cnt 新图的顶点数量, adj 新图, col 旧图节点对应的新图节点 + * @param siz 旧图每一个边双中点的数量 + * @param bridge 全部割边, direct 非割边定向 + */ + vector siz(cnt + 1); + vector> adj(cnt + 1); for (int i = 1; i <= n; i++) { siz[col[i]]++; - for (auto j : ver[i]) { + for (auto &[j, id] : ver[i]) { int x = col[i], y = col[j]; if (x != y) { adj[x].push_back(y); diff --git "a/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/README.md" "b/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/README.md" index 6b76788..6bb6557 100644 --- "a/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/README.md" +++ "b/02 - \346\211\223\345\215\260\347\250\277\346\250\241\346\235\277\346\261\207\346\200\273/README.md" @@ -10,6 +10,10 @@ ### 8.7(2024.10.07封包) +2024.10.20 [PATCH] + +- **重要更新**:《图论→缩点(Tarjan 算法)→(无向图)割边缩点》重构。 + 2024.10.07 - **重要更新**:《图论→二分图最大匹配→HopcroftKarp算法(基于最大流)解》重构,此前的版本可能被卡(时间与正确性均)。