Skip to content

Commit

Permalink
BronKerbosch bug fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
old-yan committed Jun 19, 2024
1 parent 546a650 commit e01eda2
Show file tree
Hide file tree
Showing 40 changed files with 651 additions and 91 deletions.
1 change: 1 addition & 0 deletions DS/Cartesiantree.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
​ 练习题目:

1. [P5854 【模板】笛卡尔树](https://www.luogu.com.cn/problem/P5854)
2. [Cartesian Tree](https://judge.yosupo.jp/problem/cartesian_tree)(https://github.com/yosupo06/library-checker-problems/issues/554)

### 二、模板功能

Expand Down
1 change: 1 addition & 0 deletions DS/FHQCounter.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
3. [P6136 【模板】普通平衡树(数据加强版)](https://www.luogu.com.cn/problem/P6136)
4. [P8496 [NOI2022] 众数](https://www.luogu.com.cn/problem/P8496)
5. [P9233 [蓝桥杯 2023 省 A] 颜色平衡树](https://www.luogu.com.cn/problem/P9233)
6. [Point Set Range Frequency](https://judge.yosupo.jp/problem/point_set_range_frequency)(https://github.com/yosupo06/library-checker-problems/issues/769)


### 二、模板功能
Expand Down
2 changes: 2 additions & 0 deletions DS/GlobalHashMap.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
8. [P8306 【模板】字典树](https://www.luogu.com.cn/problem/P8306)
9. [J. Range Sets](https://qoj.ac/contest/1399/problem/7641)
10. [Associative Array](https://judge.yosupo.jp/problem/associative_array)(https://github.com/yosupo06/library-checker-problems/issues/376)
11. [Point Set Range Frequency](https://judge.yosupo.jp/problem/point_set_range_frequency)(https://github.com/yosupo06/library-checker-problems/issues/769)



### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions DS/SqrtTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
11. [P4556 [Vani有约会] 雨天的尾巴 /【模板】线段树合并](https://www.luogu.com.cn/problem/P4556)
12. [P7261 [COCI2009-2010#3] PATULJCI](https://www.luogu.com.cn/problem/P7261)
13. [Static RMQ](https://judge.yosupo.jp/problem/staticrmq)(https://github.com/yosupo06/library-checker-problems/issues/34)
14. [Lowest Common Ancestor](https://judge.yosupo.jp/problem/lca)(https://github.com/yosupo06/library-checker-problems/issues/35)


### 二、模板功能
Expand Down
120 changes: 72 additions & 48 deletions GRAPH/BronKerbosch.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,14 @@ namespace OY {
return res + std::popcount(m_mask[index] & ((MaskType(1) << (range & (mask_size - 1))) - 1));
}
}
size_type count_zero(size_type first, size_type range) const {
if constexpr (mask_count == 1)
return mask_size - std::popcount(m_mask[0] | ~((MaskType(1) << range) - (MaskType(1) << first)));
else if (range < mask_size)
return mask_size - std::popcount(m_mask[0] | ~((MaskType(1) << range) - (MaskType(1) << first)));
else
return count_zero(range) - count_zero(first - 1);
}
size_type count_zero(size_type range) const {
if constexpr (mask_count == 1)
return mask_size - std::popcount(m_mask[0] | -(MaskType(1) << range));
Expand Down Expand Up @@ -75,49 +83,51 @@ namespace OY {
};
size_type m_vertex_cnt, m_max_clique, m_max_independant_set;
node m_adj[MAX_VERTEX];
bool _dfs_clique(size_type cur, size_type cnt, node &&next, std::vector<size_type> &suf) {
void _dfs_clique(size_type cur, size_type cnt, node &&next, const std::vector<std::pair<size_type, size_type>> &suf, size_type thresh) {
if (cnt + next.count_one(m_vertex_cnt) > m_max_clique) {
while (true) {
size_type nx = next.find_one(cur + 1);
if (nx == m_vertex_cnt || cnt + suf[nx] <= m_max_clique) break;
if (_dfs_clique(nx, cnt + 1, next & m_adj[nx], suf)) return true;
if (nx == m_vertex_cnt || cnt + suf[nx].second <= m_max_clique) break;
if (cnt + suf[nx].first > m_max_clique) {
_dfs_clique(nx, cnt + 1, next & m_adj[nx], suf, thresh);
if (m_max_clique == thresh) return;
}
cur = nx;
}
if (cnt > m_max_clique) return m_max_clique = cnt, true;
if (cnt > m_max_clique) m_max_clique = cnt;
}
return false;
}
bool _dfs_independant_set(size_type cur, size_type cnt, node &&next, std::vector<size_type> &suf) {
if (cnt + next.count_zero(m_vertex_cnt) > m_max_independant_set) {
void _dfs_independant_set(size_type cur, size_type cnt, node &&next, const std::vector<std::pair<size_type, size_type>> &suf, size_type thresh) {
if (cnt + next.count_zero(cur + 1, m_vertex_cnt) > m_max_independant_set) {
while (true) {
size_type nx = next.find_zero(cur + 1);
if (nx == m_vertex_cnt || cnt + suf[nx] <= m_max_independant_set) break;
if (_dfs_independant_set(nx, cnt + 1, next | m_adj[nx], suf)) return true;
if (nx == m_vertex_cnt || cnt + suf[nx].second <= m_max_independant_set) break;
if (cnt + suf[nx].first > m_max_independant_set) {
_dfs_independant_set(nx, cnt + 1, next | m_adj[nx], suf, thresh);
if (m_max_independant_set == thresh) return;
}
cur = nx;
}
if (cnt > m_max_independant_set) return m_max_independant_set = cnt, true;
if (cnt > m_max_independant_set) m_max_independant_set = cnt;
}
return false;
}
bool _find_clique(size_type cur, size_type cnt, node &&next, std::vector<size_type> &suf, std::vector<size_type> &res) {
bool _find_clique(size_type cur, size_type cnt, node &&next, const std::vector<std::pair<size_type, size_type>> &suf, std::vector<size_type> &res) {
if (cnt == m_max_clique) return res.push_back(cur), true;
if (cnt + next.count_one(m_vertex_cnt) >= m_max_clique)
while (true) {
size_type nx = next.find_one(cur + 1);
if (nx == m_vertex_cnt || cnt + suf[nx] < m_max_clique) break;
if (_find_clique(nx, cnt + 1, next & m_adj[nx], suf, res)) return res.push_back(cur), true;
cur = nx;
for (size_type x = cur, nx;; x = nx) {
nx = next.find_one(x + 1);
if (nx == m_vertex_cnt || cnt + suf[nx].second < m_max_clique) break;
if (cnt + suf[nx].first >= m_max_clique && _find_clique(nx, cnt + 1, next & m_adj[nx], suf, res)) return res.push_back(cur), true;
}
return false;
}
bool _find_independant_set(size_type cur, size_type cnt, node &&next, std::vector<size_type> &suf, std::vector<size_type> &res) {
bool _find_independant_set(size_type cur, size_type cnt, node &&next, const std::vector<std::pair<size_type, size_type>> &suf, std::vector<size_type> &res) {
if (cnt == m_max_independant_set) return res.push_back(cur), true;
if (cnt + next.count_zero(m_vertex_cnt) >= m_max_independant_set)
while (true) {
size_type nx = next.find_zero(cur + 1);
if (nx == m_vertex_cnt || cnt + suf[nx] < m_max_independant_set) break;
if (_find_independant_set(nx, cnt + 1, next | m_adj[nx], suf, res)) return res.push_back(cur), true;
cur = nx;
if (cnt + next.count_zero(cur + 1, m_vertex_cnt) >= m_max_independant_set)
for (size_type x = cur, nx;; x = nx) {
nx = next.find_zero(x + 1);
if (nx == m_vertex_cnt || cnt + suf[nx].second < m_max_independant_set) break;
if (cnt + suf[nx].first >= m_max_independant_set && _find_independant_set(nx, cnt + 1, next | m_adj[nx], suf, res)) return res.push_back(cur), true;
}
return false;
}
Expand Down Expand Up @@ -152,63 +162,77 @@ namespace OY {
m_adj[i].set_true(j);
}
size_type max_clique() {
m_max_clique = 0;
std::vector<size_type> suf(m_vertex_cnt);
std::vector<std::pair<size_type, size_type>> suf(m_vertex_cnt);
size_type his_max{};
for (size_type i = 0; i != m_vertex_cnt; i++) m_adj[i].set_true(m_vertex_cnt);
for (size_type first = m_vertex_cnt - 1; ~first; first--) {
_dfs_clique(first, 1, std::move(m_adj[first]), suf);
suf[first] = m_max_clique;
m_max_clique = 0;
_dfs_clique(first, 1, std::move(m_adj[first]), suf, his_max + 1);
suf[first].first = m_max_clique;
if (m_max_clique > his_max) his_max = m_max_clique;
suf[first].second = his_max;
}
return m_max_clique;
return m_max_clique = his_max;
}
size_type max_independant_set() {
m_max_independant_set = 0;
std::vector<size_type> suf(m_vertex_cnt);
std::vector<std::pair<size_type, size_type>> suf(m_vertex_cnt);
size_type his_max{};
for (size_type i = 0; i != m_vertex_cnt; i++) m_adj[i].set_false(m_vertex_cnt);
for (size_type first = m_vertex_cnt - 1; ~first; first--) {
_dfs_independant_set(first, 1, std::move(m_adj[first]), suf);
suf[first] = m_max_independant_set;
m_max_independant_set = 0;
_dfs_independant_set(first, 1, std::move(m_adj[first]), suf, his_max + 1);
suf[first].first = m_max_independant_set;
if (m_max_independant_set > his_max) his_max = m_max_independant_set;
suf[first].second = his_max;
}
return m_max_independant_set;
return m_max_independant_set = his_max;
}
std::vector<size_type> get_max_clique() {
m_max_clique = 0;
std::vector<size_type> suf(m_vertex_cnt);
std::vector<std::pair<size_type, size_type>> suf(m_vertex_cnt);
size_type his_max{};
for (size_type i = 0; i != m_vertex_cnt; i++) m_adj[i].set_true(m_vertex_cnt);
for (size_type first = m_vertex_cnt - 1; ~first; first--) {
_dfs_clique(first, 1, std::move(m_adj[first]), suf);
suf[first] = m_max_clique;
m_max_clique = 0;
_dfs_clique(first, 1, std::move(m_adj[first]), suf, his_max + 1);
suf[first].first = m_max_clique;
if (m_max_clique > his_max) his_max = m_max_clique;
suf[first].second = his_max;
}
std::vector<size_type> res;
res.reserve(m_max_clique);
size_type first = std::find(suf.begin(), suf.end(), m_max_clique) - suf.begin();
res.reserve(m_max_clique = his_max);
size_type first = 0;
while (suf[first].first != his_max) first++;
_find_clique(first, 1, std::move(m_adj[first]), suf, res);
std::reverse(res.begin(), res.end());
return res;
}
std::vector<size_type> get_max_independant_set() {
m_max_independant_set = 0;
std::vector<size_type> suf(m_vertex_cnt);
std::vector<std::pair<size_type, size_type>> suf(m_vertex_cnt);
size_type his_max{};
for (size_type i = 0; i != m_vertex_cnt; i++) m_adj[i].set_false(m_vertex_cnt);
for (size_type first = m_vertex_cnt - 1; ~first; first--) {
_dfs_independant_set(first, 1, std::move(m_adj[first]), suf);
suf[first] = m_max_independant_set;
m_max_independant_set = 0;
_dfs_independant_set(first, 1, std::move(m_adj[first]), suf, his_max + 1);
suf[first].first = m_max_independant_set;
if (m_max_independant_set > his_max) his_max = m_max_independant_set;
suf[first].second = his_max;
}
std::vector<size_type> res;
res.reserve(m_max_independant_set);
size_type first = std::find(suf.begin(), suf.end(), m_max_independant_set) - suf.begin();
res.reserve(m_max_independant_set = his_max);
size_type first = 0;
while (suf[first].first != his_max) first++;
_find_independant_set(first, 1, std::move(m_adj[first]), suf, res);
std::reverse(res.begin(), res.end());
return res;
}
template <typename Callback>
void do_for_each_clique(Callback &&call) {
void enumerate_clique(Callback &&call) {
for (size_type i = 0; i != m_vertex_cnt; i++) m_adj[i].set_true(m_vertex_cnt);
std::vector<size_type> clique;
for (size_type first = 0; first != m_vertex_cnt; first++) _dfs_clique(first, 1, std::move(m_adj[first]), clique, call);
}
template <typename Callback>
void do_for_each_independant_set(Callback &&call) {
void enumerate_independant_set(Callback &&call) {
for (size_type i = 0; i != m_vertex_cnt; i++) m_adj[i].set_false(m_vertex_cnt);
std::vector<size_type> independant_set;
for (size_type first = 0; first != m_vertex_cnt; first++) _dfs_independant_set(first, 1, std::move(m_adj[first]), independant_set, call);
Expand Down
7 changes: 4 additions & 3 deletions GRAPH/BronKerbosch.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@

​ 练习题目:

1. [P2423 [HEOI2012] 朋友圈](https://www.luogu.com.cn/problem/P2423)
1. [Maximum Clique](https://acm.hdu.edu.cn/showproblem.php?pid=1530)
2. [P4212 外太空旅行](https://www.luogu.com.cn/problem/P4212)
3. [Maximum Independent Set](https://judge.yosupo.jp/problem/maximum_independent_set)(https://github.com/yosupo06/library-checker-problems/issues/151)


### 二、模板功能
Expand Down Expand Up @@ -162,12 +163,12 @@ int main() {
for (int i = 0; i < max_independant_set.size(); i++) cout << max_independant_set[i] << " \n"[i == max_independant_set.size() - 1];
// 遍历所有的团
cout << "cliques:\n";
G.do_for_each_clique([](const std::vector<uint32_t> &clique) {
G.enumerate_clique([](const std::vector<uint32_t> &clique) {
for (int i = 0; i < clique.size(); i++) cout << clique[i] << " \n"[i == clique.size() - 1];
});
// 遍历所有的独立集
cout << "independant sets:\n";
G.do_for_each_independant_set([](const std::vector<uint32_t> &independant_set) {
G.enumerate_independant_set([](const std::vector<uint32_t> &independant_set) {
for (int i = 0; i < independant_set.size(); i++) cout << independant_set[i] << " \n"[i == independant_set.size() - 1];
});
}
Expand Down
1 change: 1 addition & 0 deletions GRAPH/Dijkstra_heap.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
1. [P3371 【模板】单源最短路径(弱化版)](https://www.luogu.com.cn/problem/P3371)
2. [P4779 【模板】单源最短路径(标准版)](https://www.luogu.com.cn/problem/P4779)
3. [#622. 单源最短路径](https://uoj.ac/problem/622)
4. [Shortest Path](https://judge.yosupo.jp/problem/shortest_path)(https://github.com/yosupo06/library-checker-problems/issues/173)


### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions GRAPH/Edmonds_tarjan.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
1. [P4716 【模板】最小树形图](https://www.luogu.com.cn/problem/P4716)
2. [U122738 【模板】最小树形图 2](https://www.luogu.com.cn/problem/U122738)
3. [U210116 【模板】最小树形图(加强版)](https://www.luogu.com.cn/problem/U210116)
4. [Directed MST](https://judge.yosupo.jp/problem/directedmst)(https://github.com/yosupo06/library-checker-problems/issues/39)


### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions GRAPH/EulerPath_dg.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ namespace OY {
Solver(size_type vertex_cnt, size_type edge_cnt) { m_vertex_cnt = vertex_cnt, m_edge_cnt = edge_cnt, m_edge_id = edge_cnt, m_zero_cnt = 0, m_source = -1, m_iter = s_buffer + s_use_count, m_edges = s_edge_buffer + s_edge_use_count, s_use_count += m_vertex_cnt, s_edge_use_count += m_edge_cnt; }
template <typename Traverser, typename FindBegin, typename FindEnd, typename FindNext, typename Callback>
void run(size_type prefer_source, Traverser &&traverser, FindBegin &&find_begin, FindEnd &&find_end, FindNext &&find_next, Callback &&call) {
if (!m_edge_cnt) return void(m_source = prefer_source);
for (size_type from = 0; from != m_vertex_cnt; from++) {
size_type begin = find_begin(from), end = find_end(from);
m_iter[from].m_cur = begin, m_iter[from].m_end = end;
Expand Down
1 change: 1 addition & 0 deletions GRAPH/EulerPath_dg.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
1. [P1127 词链](https://www.luogu.com.cn/problem/P1127)
2. [P7771 【模板】欧拉路径](https://www.luogu.com.cn/problem/P7771)
3. [#117. 欧拉回路](https://uoj.ac/problem/117)
4. [Eulerian Trail (Directed)](https://judge.yosupo.jp/problem/eulerian_trail_directed)(https://github.com/yosupo06/library-checker-problems/issues/25)


### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions GRAPH/EulerPath_udg.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ namespace OY {
Solver(size_type vertex_cnt, size_type edge_cnt) { m_vertex_cnt = vertex_cnt, m_edge_cnt = edge_cnt, m_edge_id = edge_cnt, m_even_cnt = 0, m_source = -1, m_iter = s_buffer + s_use_count, m_edges = s_edge_buffer + s_edge_use_count, m_visit = s_visit_buffer + s_edge_use_count, s_use_count += m_vertex_cnt, s_edge_use_count += m_edge_cnt; }
template <typename Traverser, typename FindBegin, typename FindEnd, typename FindNext, typename Callback>
void run(size_type prefer_source, Traverser &&traverser, FindBegin &&find_begin, FindEnd &&find_end, FindNext &&find_next, Callback &&call) {
if (!m_edge_cnt) return void(m_source = prefer_source);
for (size_type from = 0; from != m_vertex_cnt; from++) {
size_type begin = find_begin(from), end = find_end(from);
m_iter[from].m_cur = begin, m_iter[from].m_end = end;
Expand Down
1 change: 1 addition & 0 deletions GRAPH/EulerPath_udg.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
1. [P1341 无序字母对](https://www.luogu.com.cn/problem/P1341)
2. [P2731 [USACO3.3] 骑马修栅栏 Riding the Fences](https://www.luogu.com.cn/problem/P2731)
3. [#117. 欧拉回路](https://uoj.ac/problem/117)
4. [Eulerian Trail (Directed)](https://judge.yosupo.jp/problem/eulerian_trail_directed)(https://github.com/yosupo06/library-checker-problems/issues/25)


### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions GRAPH/HopcroftKarp.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

1. [P3386 【模板】二分图最大匹配](https://www.luogu.com.cn/problem/P3386)
2. [#78. 二分图最大匹配](https://uoj.ac/problem/78)
3. [Matching on Bipartite Graph](https://judge.yosupo.jp/problem/bipartitematching)(https://github.com/yosupo06/library-checker-problems/issues/37)


### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions GRAPH/Kruskal.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
​ 练习题目:

1. [P3366 【模板】最小生成树](https://www.luogu.com.cn/problem/P3366)
2. [Minimum Spanning Tree](https://judge.yosupo.jp/problem/minimum_spanning_tree)(https://github.com/yosupo06/library-checker-problems/issues/953)


### 二、模板功能
Expand Down
1 change: 1 addition & 0 deletions GRAPH/KthPath.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
​ 练习题目:

1. [P2483 【模板】k 短路 / [SDOI2010] 魔法猪学院](https://www.luogu.com.cn/problem/P2483)
2. [K-Shortest Walk](https://judge.yosupo.jp/problem/k_shortest_walk)(https://github.com/yosupo06/library-checker-problems/issues/509)

### 二、模板功能

Expand Down
1 change: 1 addition & 0 deletions GRAPH/Tarjan_bridge.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
5. [U134060 【模板】割边(桥)](https://www.luogu.com.cn/problem/U134060)
6. [U143936 割边/桥(模板)](https://www.luogu.com.cn/problem/U143936)
7. [U238155 【模板】割边](https://www.luogu.com.cn/problem/U238155)
8. [Two-Edge-Connected Components](https://judge.yosupo.jp/problem/two_edge_connected_components)(https://github.com/yosupo06/library-checker-problems/issues/366)

### 二、模板功能

Expand Down
Loading

0 comments on commit e01eda2

Please sign in to comment.