Skip to content

Commit

Permalink
fix aszkw bug; add dijkstra-naive; add dijk-kpath, spfa-kpath; fix do…
Browse files Browse the repository at this point in the history
…ubling-lca/lsd bug;
  • Loading branch information
old-yan committed Nov 10, 2024
1 parent 03375b0 commit 1acb02f
Show file tree
Hide file tree
Showing 51 changed files with 2,010 additions and 531 deletions.
4 changes: 3 additions & 1 deletion DS/AssignZkwTree.h
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,9 @@ namespace OY {
void resize(size_type length) {
if (!(m_size = length)) return;
m_dep = std::max<size_type>(1, std::bit_width(m_size - 1)), m_cap = 1 << m_dep;
m_sub.assign(m_cap * 2, group::identity());
node it{};
it.m_val = group::identity();
m_sub.assign(m_cap * 2, it);
}
template <typename InitMapping>
void resize(size_type length, InitMapping mapping) {
Expand Down
32 changes: 0 additions & 32 deletions DS/FastHeap.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,38 +81,6 @@ namespace OY {
bool empty() const { return !m_size; }
size_type size() const { return m_size; }
bool contains(size_type x) const { return ~m_pos[x]; }
void check() const {
if (empty()) return;
int L = m_size, R = m_size * 2 - 1, cnt = 0;
for (int i = 0; i < m_pos.size(); i++)
if (~m_pos[i]) {
if (!(L <= m_pos[i] and m_pos[i] <= R)) {
exit(1);
}
if (m_heap[m_pos[i]] != i) {
exit(2);
}
cnt++;
}
if (cnt != m_size) {
exit(3);
}
for (int i = m_size - 1; i; i--) {
if (m_heap[i] != m_heap[i * 2] and m_heap[i] != m_heap[i * 2 + 1]) {
exit(4);
}
if (m_heap[i] == m_heap[i * 2]) {
if (m_comp(m_map(m_heap[i * 2]), m_map(m_heap[i * 2 + 1]))) {
exit(5);
}
}
if (m_heap[i] == m_heap[i * 2 + 1]) {
if (m_comp(m_map(m_heap[i * 2 + 1]), m_map(m_heap[i * 2]))) {
exit(6);
}
}
}
}
};
}
template <typename Tp, typename Compare = std::less<Tp>, typename HeapType = FHeap::Heap<FHeap::Getter<std::vector<Tp>>, Compare>>
Expand Down
4 changes: 4 additions & 0 deletions DS/FastHeap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

​ 数据结构:快速二叉堆。

​ 练习题目:

1. [find the safest road](https://acm.hdu.edu.cn/showproblem.php?pid=1596)

### 二、模板功能

​ 本堆核心为二叉堆,在此基础上做了一些优化。
Expand Down
5 changes: 5 additions & 0 deletions DS/SiftHeap.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

​ 数据结构:原地升降二叉堆。

​ 练习题目:

1. [find the safest road](https://acm.hdu.edu.cn/showproblem.php?pid=1596)


### 二、模板功能

​ 本堆核心为二叉堆,在此基础上做了一些优化。
Expand Down
2 changes: 1 addition & 1 deletion GRAPH/BellmanFord.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ namespace OY {
using value_type = ValueType;
using sum_type = ValueType;
using compare_type = Compare;
static sum_type op(const sum_type &x, const sum_type &y) { return std::max(x, y); }
static sum_type op(const sum_type &x, const value_type &y) { return std::max(x, y); }
static sum_type identity() { return {}; }
static sum_type infinite() { return Inf; }
};
Expand Down
13 changes: 5 additions & 8 deletions GRAPH/BellmanFord.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@

​ 练习题目:

1. [P1608 路径统计](https://www.luogu.com.cn/problem/P1608)
2. [P2047 [NOI2007] 社交网络](https://www.luogu.com.cn/problem/P2047)
3. [P3371 【模板】单源最短路径(弱化版)](https://www.luogu.com.cn/problem/P3371)
4. [P3385 【模板】负环](https://www.luogu.com.cn/problem/P3385)
1. [Deleting Edges](https://acm.hdu.edu.cn/showproblem.php?pid=6026)
2. [P1608 路径统计](https://www.luogu.com.cn/problem/P1608)
3. [P2047 [NOI2007] 社交网络](https://www.luogu.com.cn/problem/P2047)
4. [P3371 【模板】单源最短路径(弱化版)](https://www.luogu.com.cn/problem/P3371)
5. [P3385 【模板】负环](https://www.luogu.com.cn/problem/P3385)


### 二、模板功能
Expand Down Expand Up @@ -180,10 +181,6 @@ void test_distance_sum() {

// 如果模板参数为 true,那么查询器还可以查询最短路的结点编号
using group = OY::BellmanFord::AddGroup<int>;
// 第一个参数表示距离求和
// 第二个参数表示不计数
// 第三个参数表示求最小距离
// 第四个参数表示要保存路径

auto table2 = G.calc<group, void, true>(0).first;
table2.trace(
Expand Down
39 changes: 18 additions & 21 deletions GRAPH/Dijkstra_heap.h → GRAPH/Dijkstra.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@ gcc11.2,c++11
clang12.0,C++11
msvc14.2,C++14
*/
#ifndef __OY_DIJKSTRA_HEAP__
#define __OY_DIJKSTRA_HEAP__
#ifndef __OY_DIJKSTRA__
#define __OY_DIJKSTRA__

#include <limits>
#include <type_traits>

#include "../DS/FastHeap.h"

namespace OY {
namespace DijkstraHeap {
namespace Dijkstra {
using size_type = uint32_t;
template <typename Tp, typename CountType, bool GetPath>
struct DistanceNode {
Expand Down Expand Up @@ -65,7 +65,7 @@ namespace OY {
using value_type = ValueType;
using sum_type = ValueType;
using compare_type = Compare;
static sum_type op(const sum_type &x, const sum_type &y) { return std::max(x, y); }
static sum_type op(const sum_type &x, const value_type &y) { return std::max(x, y); }
static sum_type identity() { return {}; }
static sum_type infinite() { return Inf; }
};
Expand All @@ -74,20 +74,21 @@ namespace OY {
template <typename Tp1, typename Tp2>
bool operator()(const Tp1 &x, const Tp2 &y) const { return Compare()(y, x); }
};
template <typename Group, typename CountType = void, bool GetPath = false>
template <typename Group, typename CountType = void, bool GetPath = false, template <typename, typename> typename Heap = FastHeap>
struct Solver {
using group = Group;
using value_type = typename group::value_type;
using sum_type = typename group::sum_type;
using compare_type = typename group::compare_type;
using heap_type = Heap<Getter<sum_type, CountType, GetPath>, LessToGreater<compare_type>>;
using node = DistanceNode<sum_type, CountType, GetPath>;
static constexpr bool has_count = !std::is_void<CountType>::value;
using count_type = typename std::conditional<has_count, CountType, bool>::type;
size_type m_vertex_cnt;
std::vector<node> m_distance;
FastHeap<Getter<sum_type, CountType, GetPath>, LessToGreater<compare_type>> m_heap;
heap_type m_heap;
static sum_type infinite() { return group::infinite(); }
Solver(size_type vertex_cnt) : m_vertex_cnt(vertex_cnt), m_distance(vertex_cnt), m_heap(vertex_cnt, m_distance.data(), {}) {
Solver(size_type vertex_cnt) : m_vertex_cnt(vertex_cnt), m_distance(vertex_cnt), m_heap(vertex_cnt, m_distance.data()) {
for (size_type i = 0; i != m_vertex_cnt; i++) {
m_distance[i].m_val = infinite();
if constexpr (GetPath) m_distance[i].m_from = -1;
Expand All @@ -98,13 +99,12 @@ namespace OY {
if constexpr (has_count) m_distance[i].m_cnt = cnt;
m_heap.push(i);
}
template <bool Break = false, typename Traverser>
template <typename Traverser>
void run(size_type target, Traverser &&traverser) {
while (!m_heap.empty()) {
size_type from = m_heap.top();
m_heap.pop();
if constexpr (Break)
if (from == target) break;
if (from == target) break;
auto d = m_distance[from].m_val;
if (!compare_type()(d, infinite())) break;
traverser(from, [&](size_type to, const value_type &dis) {
Expand All @@ -115,7 +115,7 @@ namespace OY {
if constexpr (GetPath) m_distance[to].m_from = from;
m_heap.push(to);
} else if (!compare_type()(m_distance[to].m_val, to_dis))
m_distance[to].m_cnt += m_distance[from].m_cnt, m_heap.push(to);
m_distance[to].m_cnt += m_distance[from].m_cnt;
} else if (compare_type()(to_dis, m_distance[to].m_val)) {
m_distance[to].m_val = to_dis;
if constexpr (GetPath) m_distance[to].m_from = from;
Expand Down Expand Up @@ -171,24 +171,21 @@ namespace OY {
m_starts.assign(m_vertex_cnt + 1, {});
}
void add_edge(size_type a, size_type b, Tp dis) { m_starts[a + 1]++, m_raw_edges.push_back({a, b, dis}); }
template <typename Group = AddGroup<Tp>, typename CountType = void, bool GetPath = false>
Solver<Group, CountType, GetPath> calc(size_type source, size_type target = -1) const {
template <typename Group = AddGroup<Tp>, typename CountType = void, bool GetPath = false, template <typename, typename> typename Heap = FastHeap>
Solver<Group, CountType, GetPath, Heap> calc(size_type source, size_type target = -1) const {
if (!m_prepared) _prepare();
Solver<Group, CountType, GetPath> sol(m_vertex_cnt);
Solver<Group, CountType, GetPath, Heap> sol(m_vertex_cnt);
sol.set_distance(source, Group::identity());
if (~target)
sol.template run<true>(target, *this);
else
sol.template run<false>(-1, *this);
sol.run(target, *this);
return sol;
}
template <typename Group = AddGroup<Tp>>
template <typename Group = AddGroup<Tp>, template <typename, typename> typename Heap = FastHeap>
std::vector<size_type> get_path(size_type source, size_type target) const {
if (!m_prepared) _prepare();
std::vector<size_type> res;
Solver<Group, void, true> sol(m_vertex_cnt);
Solver<Group, void, true, Heap> sol(m_vertex_cnt);
sol.set_distance(source, Group::identity());
sol.template run<true>(target, *this);
sol.run(target, *this);
res.push_back(source);
sol.trace(target, [&](size_type from, size_type to) { res.push_back(to); });
return res;
Expand Down
48 changes: 23 additions & 25 deletions GRAPH/Dijkstra_heap.md → GRAPH/Dijkstra.md
Original file line number Diff line number Diff line change
@@ -1,21 +1,23 @@
### 一、模板类别

​ 数据结构:`Dijkstra` 算法的堆实现
​ 数据结构:`Dijkstra` 算法

​ 练习题目:

1. [find the safest road](https://acm.hdu.edu.cn/showproblem.php?pid=1596)
2. [最短路径问题](https://acm.hdu.edu.cn/showproblem.php?pid=3790)
3. [1631. 最小体力消耗路径](https://leetcode.cn/problems/path-with-minimum-effort/)
4. [3123. 最短路径中的边](https://leetcode.cn/problems/find-edges-in-shortest-paths/)
5. [P1576 最小花费](https://www.luogu.com.cn/problem/P1576)
6. [P1608 路径统计](https://www.luogu.com.cn/problem/P1608)
7. [P2047 [NOI2007] 社交网络](https://www.luogu.com.cn/problem/P2047)
8. [P3371 【模板】单源最短路径(弱化版)](https://www.luogu.com.cn/problem/P3371)
9. [P4779 【模板】单源最短路径(标准版)](https://www.luogu.com.cn/problem/P4779)
10. [P6822 [PA2012] Tax](https://www.luogu.com.cn/problem/P6822)
11. [#622. 单源最短路径](https://uoj.ac/problem/622)
12. [Shortest Path](https://judge.yosupo.jp/problem/shortest_path)(https://github.com/yosupo06/library-checker-problems/issues/173)
3. [Deleting Edges](https://acm.hdu.edu.cn/showproblem.php?pid=6026)
4. [1631. 最小体力消耗路径](https://leetcode.cn/problems/path-with-minimum-effort/)
5. [3123. 最短路径中的边](https://leetcode.cn/problems/find-edges-in-shortest-paths/)
6. [P1491 集合位置](https://www.luogu.com.cn/problem/P1491)
7. [P1576 最小花费](https://www.luogu.com.cn/problem/P1576)
8. [P1608 路径统计](https://www.luogu.com.cn/problem/P1608)
9. [P2047 [NOI2007] 社交网络](https://www.luogu.com.cn/problem/P2047)
10. [P3371 【模板】单源最短路径(弱化版)](https://www.luogu.com.cn/problem/P3371)
11. [P4779 【模板】单源最短路径(标准版)](https://www.luogu.com.cn/problem/P4779)
12. [P6822 [PA2012] Tax](https://www.luogu.com.cn/problem/P6822)
13. [#622. 单源最短路径](https://uoj.ac/problem/622)
14. [Shortest Path](https://judge.yosupo.jp/problem/shortest_path)(https://github.com/yosupo06/library-checker-problems/issues/173)


### 二、模板功能
Expand Down Expand Up @@ -143,16 +145,16 @@
### 三、模板示例

```c++
#include "GRAPH/Dijkstra_heap.h"
#include "GRAPH/Dijkstra.h"
#include "IO/FastIO.h"
#include "TEST/std_bit.h"

void test_distance_sum() {
// 普通使用者只需要了解熟悉 OY::DijkstraHeap::Graph 的使用
// 普通使用者只需要了解熟悉 OY::Dijkstra::Graph 的使用
cout << "test distance sum:\n";

// 建图
OY::DijkstraHeap::Graph<int> G(7, 9);
OY::Dijkstra::Graph<int> G(7, 9);
// 注意加的边都是有向边
G.add_edge(0, 1, 100);
G.add_edge(0, 2, 200);
Expand All @@ -171,11 +173,7 @@ void test_distance_sum() {
cout << "min dis from 0 to 6:" << table.query(6) << endl;

// 如果模板参数为 true,那么查询器还可以查询最短路的结点编号
using group = OY::DijkstraHeap::AddGroup<int>;
// 第一个参数表示距离求和
// 第二个参数表示不计数
// 第三个参数表示求最小距离
// 第四个参数表示要保存路径
using group = OY::Dijkstra::AddGroup<int>;

auto table2 = G.calc<group, void, true>(0);
table2.trace(6, [](int from, int to) { cout << "go from " << from << " -> " << to << endl; });
Expand All @@ -188,7 +186,7 @@ void test_distance_sum() {
void test_distance_max() {
cout << "test distance max:\n";

OY::DijkstraHeap::Graph<int> G(7, 9);
OY::Dijkstra::Graph<int> G(7, 9);
G.add_edge(0, 1, 100);
G.add_edge(0, 2, 200);
G.add_edge(3, 4, 100);
Expand All @@ -201,7 +199,7 @@ void test_distance_max() {

// 定义路径长度为路径中的边长的最大值
// 获取最短路查询器
using group = OY::DijkstraHeap::MaxGroup<int>;
using group = OY::Dijkstra::MaxGroup<int>;
auto table = G.calc<group>(0);
cout << "min dis from 0 to 0:" << table.query(0) << endl;
cout << "min dis from 0 to 2:" << table.query(2) << endl;
Expand All @@ -212,15 +210,15 @@ void test_distance_max() {
void test_count() {
cout << "test path count:\n";

OY::DijkstraHeap::Graph<int> G(4, 5);
OY::Dijkstra::Graph<int> G(4, 5);
G.add_edge(0, 1, 100);
G.add_edge(1, 2, 200);
G.add_edge(2, 3, 100);
G.add_edge(0, 2, 300);
G.add_edge(1, 3, 300);

// 获取最短路路径数查询器
using monoid = OY::DijkstraHeap::AddGroup<int>;
using monoid = OY::Dijkstra::AddGroup<int>;
auto table = G.calc<monoid, int>(0);
cout << "min dis from 0 to 3:" << table.query(3) << endl;
cout << "path count:" << table.query_count(3) << endl;
Expand All @@ -244,8 +242,8 @@ void test_solver() {
adj[5].push_back({6, 200});

// 直接建一个可追溯最短路的解答器
using group = OY::DijkstraHeap::AddGroup<int, int64_t>;
OY::DijkstraHeap::Solver<group, void, true> sol(7);
using group = OY::Dijkstra::AddGroup<int, int64_t>;
OY::Dijkstra::Solver<group, void, true> sol(7);
sol.set_distance(0, 0);
// 传递一个遍历边的泛型回调
sol.run(-1, [&](int from, auto call) {
Expand Down
Loading

0 comments on commit 1acb02f

Please sign in to comment.