This documentation is automatically generated by online-judge-tools/verification-helper
#include "src/graph/RangeEdgeGraph.hpp"区間から区間に辺が伸びるようなグラフ上での最短路を計算する. Segment Treeの構造を利用して頂点数$3n+q$, 辺数$4n+q\log n$のグラフを構成している.
区間に辺を張るテクの実装例(Dijkstra法セット)と使用例 - Lorent’s diary
#pragma once
#include <limits>
#include <queue>
#include <vector>
template <typename T> struct RangeEdgeGraph {
public:
RangeEdgeGraph(int n) : n(n), G(3 * n) {
for (int i = 1; i < n; i++) {
int l = i << 1 | 0, r = i << 1 | 1;
add_edge(i, l, 0);
add_edge(i, r, 0);
add_edge(l + 2 * n, i + 2 * n, 0);
add_edge(r + 2 * n, i + 2 * n, 0);
}
}
void add_edge(int l1, int r1, int l2, int r2, T cost) {
int add = G.size();
G.emplace_back();
for (l1 += n, r1 += n; l1 < r1; l1 >>= 1, r1 >>= 1) {
if (l1 & 1) add_edge((l1++) + 2 * n, add, 0);
if (r1 & 1) add_edge((--r1) + 2 * n, add, 0);
}
for (l2 += n, r2 += n; l2 < r2; l2 >>= 1, r2 >>= 1) {
if (l2 & 1) G[add].emplace_back(l2++, cost);
if (r2 & 1) G[add].emplace_back(--r2, cost);
}
}
std::vector<T> build(int s) {
std::vector<T> dp(G.size(), std::numeric_limits<T>::max());
s += n;
dp[s] = 0;
std::priority_queue<edge> pq;
pq.emplace(s, dp[s]);
while (!pq.empty()) {
auto p = pq.top();
pq.pop();
int v = p.to;
if (dp[v] < p.cost) continue;
for (const auto& e : G[v]) {
int u = e.to;
if (dp[v] + e.cost < dp[u]) {
dp[u] = dp[v] + e.cost;
pq.emplace(u, dp[u]);
}
}
}
std::vector<T> res(dp.begin() + n, dp.begin() + 2 * n);
return res;
}
private:
struct edge {
int to;
T cost;
edge(int to, T cost) : to(to), cost(cost) {}
bool operator<(const edge& rhs) const { return cost > rhs.cost; }
};
int n;
std::vector<std::vector<edge>> G;
void add_edge(int u, int v, T cost) { G[(3 * n <= u ? u - 2 * n : u)].emplace_back(v, cost); }
};#line 2 "src/graph/RangeEdgeGraph.hpp"
#include <limits>
#include <queue>
#include <vector>
template <typename T> struct RangeEdgeGraph {
public:
RangeEdgeGraph(int n) : n(n), G(3 * n) {
for (int i = 1; i < n; i++) {
int l = i << 1 | 0, r = i << 1 | 1;
add_edge(i, l, 0);
add_edge(i, r, 0);
add_edge(l + 2 * n, i + 2 * n, 0);
add_edge(r + 2 * n, i + 2 * n, 0);
}
}
void add_edge(int l1, int r1, int l2, int r2, T cost) {
int add = G.size();
G.emplace_back();
for (l1 += n, r1 += n; l1 < r1; l1 >>= 1, r1 >>= 1) {
if (l1 & 1) add_edge((l1++) + 2 * n, add, 0);
if (r1 & 1) add_edge((--r1) + 2 * n, add, 0);
}
for (l2 += n, r2 += n; l2 < r2; l2 >>= 1, r2 >>= 1) {
if (l2 & 1) G[add].emplace_back(l2++, cost);
if (r2 & 1) G[add].emplace_back(--r2, cost);
}
}
std::vector<T> build(int s) {
std::vector<T> dp(G.size(), std::numeric_limits<T>::max());
s += n;
dp[s] = 0;
std::priority_queue<edge> pq;
pq.emplace(s, dp[s]);
while (!pq.empty()) {
auto p = pq.top();
pq.pop();
int v = p.to;
if (dp[v] < p.cost) continue;
for (const auto& e : G[v]) {
int u = e.to;
if (dp[v] + e.cost < dp[u]) {
dp[u] = dp[v] + e.cost;
pq.emplace(u, dp[u]);
}
}
}
std::vector<T> res(dp.begin() + n, dp.begin() + 2 * n);
return res;
}
private:
struct edge {
int to;
T cost;
edge(int to, T cost) : to(to), cost(cost) {}
bool operator<(const edge& rhs) const { return cost > rhs.cost; }
};
int n;
std::vector<std::vector<edge>> G;
void add_edge(int u, int v, T cost) { G[(3 * n <= u ? u - 2 * n : u)].emplace_back(v, cost); }
};