- B1: 前缀和与差分
- B2: 快速组合
- B3: 二分查找
- B4: 高精度加法
- B4: 高精度除法
- B4: 高精度乘法
- B4: 高精度减法
- D1: 单调栈
- D2: 单调队列
- D3: Spare Table
- D4: 字典树
- D5: 并查集
- D6: 树状数组-限定区间计数
- D6: 树状数组-单点更新区间求和
- D7: 线段树-基础
- G1: 二分图-判定
- G2: 二分图-最大匹配
- G3: Astar k短路 on matrix
- G4: 拓扑排序
- G5: 连通无环无向图的重心
- G6: MST-Kruskal
- G7: MST-Prim
- G8: ShortestPath-BellmanFord
- G9: ShortestPath-Dijkstra
- G9: ShortestPath-Dijkstra Heap OPT
- G10: ShortestPath-SPFA
- G11: ShortestPath-Floyd
- M1: 快速幂与龟速乘
- M2: 欧几里得-最大公约数
- M2: EX欧几里得-翡蜀定理
- M2: EX欧几里得-线性同余方程
- M2: EX欧几里得-乘法逆元
- M3: 费马小定理-乘法逆元
- M4: 分解质因数
- M4: 分解质因数-欧拉函数
- M4: 分解质因数-多数乘积约数计数
- M4: 分解质因数-多数乘积约数求和
- M5: 欧拉筛
- M5: 欧拉筛-质数筛
- M6: 埃氏筛-质数筛
- M7: Stein算法-最大公约数
- M8: 矩阵乘法与快速幂
- O1: 快速排序
- O2: 并归排序
- S1: KMP
- S2: 字符串哈希
template< class type >
class SPD_Dijkstra {
const int n;
unordered_set<int> vis; // 表示还没有(确定原点到该点的最短路且已经完成松弛操作)的集合.最后被动确定的点不被删除
public:
type INF = numeric_limits<type>::max()>>1u;
type dis[maxn+1] {}; // 表示源点到该点的最短路径长度
type ar[maxn+1][maxn+1] {}; // 使用邻接矩阵存储图的结构
explicit SPD_Dijkstra(const int n): n(n) { // single point shortest path for dense graph (Dijkstra)
for (int i = 1; i <= n; i++) fill(ar[i]+1, ar[i]+n+1, INF);
for (int i = 1; i <= n; i++) ar[i][i]= 0;
}
void solve(const int source) {
for (int i = 1; i <= n; i++) vis.insert(i);
fill(dis+1, dis+n+1, INF);
dis[source] = 0; // 此时虽然源点到源点的最短路为0,但还没有更新其出边,所以不能将源点从vis中删除
for (int k = 1, cur; k < n; k++) { // 确定源点到vis中最短距离的点->更新其出边->从vis中删除该点,最后一个点被动确定
cur = *vis.begin(); // 在vis中寻找距离源点最近的点
for (const auto i : vis) if (dis[i] < dis[cur]) cur = i;
vis.erase(cur);
for (const auto i : vis) dis[i] = min(dis[i], dis[cur] + ar[cur][i]); // 尝试松弛其出边
}
}
};
单源汇
template< class type >
class SP {
const type INF = numeric_limits< type >::max() >> 1u;
const int n;
unordered_set< int > vis;
type dis[maxn + 1];
public:
int ar[maxn + 1][maxn + 1] {};
explicit SP(const int n): n(n) {
for (int i = 1; i <= n; i++) {
fill(ar[i] + 1, ar[i] + n + 1, INF);
ar[i][i] = 0;
}
}
int solve(int source, int target) {
unordered_set< int >().swap(vis);
for (int i = 1; i <= n; i++) vis.insert(i);
fill(dis + 1, dis + n + 1, INF);
dis[source] = 0;
for (int k = 1, cur; k < n; k++) {
cur = *vis.begin();
for (const auto i : vis) if (dis[i] < dis[cur]) cur = i;
vis.erase(cur);
if (dis[cur] == INF) return -1;
if (cur == target) return dis[cur];
for (const auto i : vis) dis[i] = min(dis[i], dis[cur] + ar[cur][i]);
}
return dis[target] == INF ? -1 : dis[target];
}
};