This documentation is automatically generated by online-judge-tools/verification-helper
#define PROBLEM "https://judge.yosupo.jp/problem/shortest_path"
#include "./../Graph/DijkstraBuildPath.cpp"
#include <iostream>
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, s, t;
cin >> n >> m >> s >> t;
Graph g(n);
for (int i = 0; i < m; ++i) {
int a, b;
Weight c;
cin >> a >> b >> c;
g[a].emplace_back(b, c);
}
auto [dist, prev] = DijkstraBuildPrev(g, s);
auto path = BuildPath(prev, t);
if (dist[t] < INF) {
cout << dist[t] << ' ' << path.size() - 1 << endl;
for (size_t i = 0; i < path.size() - 1; i++) {
cout << path[i] << ' ' << path[i + 1] << endl;
}
} else {
cout << -1 << endl;
}
}
#line 1 "test/DijkstraBuildPath.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/shortest_path"
#line 2 "Graph/GraphTemplate.cpp"
#include <vector>
#include <utility>
#include <iostream>
#include <limits>
using Weight = long long;
constexpr Weight INF = std::numeric_limits<Weight>::max();
struct Edge {
int to;
Weight cost;
Edge() : to(-1), cost(-1) {}
Edge(int _to, Weight _cost = 1) : to(_to), cost(_cost) {}
friend bool operator<(const Edge& e1, const Edge& e2) {
return e1.cost < e2.cost;
}
friend bool operator>(const Edge& e1, const Edge& e2) {
return e1.cost > e2.cost;
}
friend std::ostream& operator<<(std::ostream& os, const Edge& e) {
return os << "->" << e.to << '(' << e.cost << ')';
}
};
using UnWeightedGraph = std::vector<std::vector<int>>;
using Graph = std::vector<std::vector<Edge>>;
struct Edge2 {
int from, to;
Weight cost;
Edge2() : from(-1), to(-1), cost(0) {}
Edge2(int _from, int _to, Weight _cost) : from(_from), to(_to), cost(_cost) {}
friend bool operator<(const Edge2& e1, const Edge2& e2) {
return e1.cost < e2.cost;
}
friend bool operator>(const Edge2& e1, const Edge2& e2) {
return e1.cost > e2.cost;
}
friend std::ostream& operator<<(std::ostream& os, const Edge2& e) {
return os << e.from << "->" << e.to << '(' << e.cost << ')';
}
};
using UnWeightedEdges = std::vector<std::pair<int, int>>;
using Edges = std::vector<Edge2>;
using Matrix = std::vector<std::vector<Weight>>;
auto add_edge(UnWeightedGraph& graph, int v, int u) {
graph[v].push_back(u);
graph[u].push_back(v);
}
auto add_edge(Graph& graph, int v, int u, Weight cost) {
graph[v].emplace_back(u, cost);
graph[u].emplace_back(v, cost);
}
auto to_graph(const UnWeightedGraph& graph, Weight cost = 1) {
Graph result(graph.size());
for (std::size_t i = 0; i < graph.size(); ++i) {
for (int v : graph[i]) {
result[i].emplace_back(v, cost);
}
}
return result;
}
auto to_unweighted_graph(const Graph& graph) {
UnWeightedGraph result(graph.size());
for (std::size_t i = 0; i < graph.size(); ++i) {
for (auto [v, cost] : graph[i]) {
result[i].push_back(v);
}
}
return result;
}
auto to_edges(const UnWeightedGraph& graph, bool unique = false) {
std::vector<std::pair<int, int>> edges;
for (std::size_t i = 0; i < graph.size(); ++i) {
for (int v : graph[i]) {
if (!unique || static_cast<int>(i) < v) edges.emplace_back(i, v);
}
}
return edges;
}
auto to_edges(const Graph& graph) {
Edges edges;
for (std::size_t i = 0; i < graph.size(); ++i) {
for (auto [v, cost] : graph[i]) {
edges.emplace_back(i, v, cost);
}
}
return edges;
}
#line 4 "Graph/DijkstraBuildPath.cpp"
#include <queue>
#include <algorithm>
#include <functional>
#line 8 "Graph/DijkstraBuildPath.cpp"
auto DijkstraBuildPrev(const Graph& graph, int s) {
std::size_t n = graph.size();
std::vector<Weight> dist(n, INF);
dist[s] = 0;
std::vector<int> prev(n, -1);
std::priority_queue<Edge, std::vector<Edge>, std::greater<Edge>> pq;
pq.emplace(s, 0);
while (!pq.empty()) {
Edge p = pq.top();
pq.pop();
int v = p.to;
if (dist[v] < p.cost) continue;
for (auto e : graph[v]) {
if (dist[e.to] > dist[v] + e.cost) {
dist[e.to] = dist[v] + e.cost;
pq.emplace(e.to, dist[e.to]);
prev[e.to] = v;
}
}
}
return std::pair(dist, prev);
}
std::vector<int> BuildPath(const std::vector<int>& prev, int t) {
std::vector<int> result;
while (prev[t] != -1) {
result.push_back(t);
t = prev[t];
}
result.push_back(t);
std::reverse(result.begin(), result.end());
return result;
}
#line 5 "test/DijkstraBuildPath.test.cpp"
using namespace std;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m, s, t;
cin >> n >> m >> s >> t;
Graph g(n);
for (int i = 0; i < m; ++i) {
int a, b;
Weight c;
cin >> a >> b >> c;
g[a].emplace_back(b, c);
}
auto [dist, prev] = DijkstraBuildPrev(g, s);
auto path = BuildPath(prev, t);
if (dist[t] < INF) {
cout << dist[t] << ' ' << path.size() - 1 << endl;
for (size_t i = 0; i < path.size() - 1; i++) {
cout << path[i] << ' ' << path[i + 1] << endl;
}
} else {
cout << -1 << endl;
}
}