結果
問題 | No.160 最短経路のうち辞書順最小 |
ユーザー |
![]() |
提出日時 | 2015-08-19 11:21:12 |
言語 | C++11(廃止可能性あり) (gcc 13.3.0) |
結果 |
AC
|
実行時間 | 17 ms / 5,000 ms |
コード長 | 7,470 bytes |
コンパイル時間 | 1,527 ms |
コンパイル使用メモリ | 185,580 KB |
実行使用メモリ | 5,376 KB |
最終ジャッジ日時 | 2024-07-18 10:28:19 |
合計ジャッジ時間 | 2,423 ms |
ジャッジサーバーID (参考情報) |
judge3 / judge5 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
sample | AC * 4 |
other | AC * 26 |
ソースコード
#include <bits/stdc++.h>using namespace std;template<typename T> class Ordered {public:template<typename V> bool operator==(const V& v) const {return !(static_cast<T>(v) < static_cast<const T&>(*this) || static_cast<const T&>(*this) < static_cast<T>(v));}template<typename V> bool operator!=(const V& v) const {return static_cast<T>(v) < static_cast<const T&>(*this) || static_cast<const T&>(*this) < static_cast<T>(v);}template<typename V> bool operator>(const V& v) const {return static_cast<T>(v) < static_cast<const T&>(*this);}template<typename V> bool operator<=(const V& v) const {return !(static_cast<T>(v) < static_cast<const T&>(*this));}template<typename V> bool operator>=(const V& v) const {return !(static_cast<const T&>(*this) < static_cast<T>(v));}};template<typename Edge> class Graph {public:typedef Edge EdgeType;virtual int size() const = 0;template<typename... Args> void addEdge(Args...) {}template<typename... Args> void addUndirectedEdge(Args...) {}virtual vector<Edge> getEdges() const = 0;virtual vector<Edge> getEdges(int from) const = 0;virtual vector<Edge> getEdges(int from, int to) const = 0;virtual int getDegree(int v) const = 0;};template<typename Edge> class AdjacencyList : public Graph<Edge> {protected:vector<vector<Edge>> graph;public:AdjacencyList(int n) : graph(n) {}int size() const {return graph.size();}template<typename... Args> void addEdge(Args... args) {Edge edge(args...);graph[edge.from].emplace_back(edge);}template<typename... Args> void addUndirectedEdge(Args... args) {Edge edge(args...);addEdge(edge);swap(edge.from, edge.to);addEdge(edge);}vector<Edge> getEdges() const {vector<Edge> res;for (const auto& edges : graph) {res.insert(res.end(), edges.begin(), edges.end());}return res;}vector<Edge> getEdges(int from) const {return graph[from];}vector<Edge> getEdges(int from, int to) const {vector<Edge> res;for (const auto& edge : graph[from]) {if (edge.to == to) res.emplace_back(edge);}return res;}int getDegree(int v) const {return graph[v].size();}vector<Edge>& operator[](int v) {return graph[v];}};template<typename Graph, typename State> class Search {protected:typedef typename Graph::EdgeType Edge;const Graph graph;vector<bool> visited;virtual void push(const State&) = 0;virtual State next() = 0;virtual bool isRunning() = 0;virtual void visit(const State&) {}virtual bool canPruning(const State&) {return false;}public:Search(const Graph& graph) : graph(graph), visited(graph.size(), false) {}void solve(int from) {push(State(from));while (isRunning()) {State now = next();int pos = now.getPos();if (visited[pos]) continue;visited[pos] = true;visit(now);for (const Edge& edge : graph.getEdges(pos)) {State nextState = now.next(edge);if (visited[nextState.getPos()]) continue;if (canPruning(nextState)) continue;push(nextState);}}}bool isReachable(int v) {return visited[v];}};template<typename Edge> class Tree {public:vector<Edge> parent;vector<vector<int>> children;vector<int> depth;Tree() {}Tree(int n) : children(n), depth(n, -1) {for (int i = 0; i < n; ++i) parent.emplace_back(i, i);}int size() const {return parent.size();}template<typename... Args> void addEdge(Args... args) {Edge edge(args...);parent[edge.from] = edge;if (edge.from != edge.to) children[edge.to].emplace_back(edge.from);}int getDepth(int v) {if (depth[v] != -1) return depth[v];if (parent[v].to == v) return depth[v] = 0;return depth[v] = getDepth(parent[v].to) + 1;}vector<int> getPath(int v) {vector<int> res{v};while (v != parent[v].to) {v = parent[v].to;res.emplace_back(v);}return res;}};template<typename Edge> struct DijkstraState {typedef typename Edge::CostType Cost;Edge edge;Cost cost;DijkstraState(int pos) : edge(pos, pos), cost(0) {}DijkstraState(const Edge& edge, Cost cost) : edge(edge), cost(cost) {}DijkstraState next(const Edge& edge) const {return DijkstraState(edge, cost + edge.cost);}bool operator<(const DijkstraState& state) const {return cost > state.cost;}int getPos() const {return edge.to;}};template<typename Graph, bool Restoration = false, typename State = DijkstraState<typename Graph::EdgeType>> class Dijkstra : public Search<Graph,State> {protected:typedef typename Graph::EdgeType Edge;typedef typename Edge::CostType Cost;const Cost INF = numeric_limits<Cost>::max();priority_queue<State> que;void push(const State& state) {que.push(state);dis[state.getPos()] = state.cost;}State next() {State now = que.top();que.pop();return now;}bool isRunning() {return !que.empty();}void visit(const State& state) {if (Restoration) {auto e = state.edge;swap(e.from, e.to);shortestPathTree.addEdge(e);}}bool canPruning(const State& state) {return dis[state.getPos()] <= state.cost;}public:vector<Cost> dis;Tree<Edge> shortestPathTree;Dijkstra(const Graph& graph) : Search<Graph, State>(graph), dis(graph.size(), INF) {if (Restoration) shortestPathTree = Tree<Edge>(graph.size());}};template<typename Graph> inline Dijkstra<Graph> shortestPath(Graph& graph, int from) {Dijkstra<Graph> dijkstra(graph);dijkstra.solve(from);return dijkstra;}template<typename Graph> inline typename Graph::EdgeType::CostType shortestPath(Graph& graph, int from, int to) {Dijkstra<Graph> dijkstra(graph);dijkstra.solve(from);return dijkstra.dis[to];}template<typename Graph> inline Dijkstra<Graph, true> shortestPathTree(Graph& graph, int from) {Dijkstra<Graph, true> dijkstra(graph);dijkstra.solve(from);return dijkstra;}template<typename T> string to_string(const T& v) {string str;for (const auto& i : const_cast<T&>(v)) str += to_string(i) + " ";return str.substr(0, max(0, (int)str.size() - 1));}struct Cost : public Ordered<Cost> {int dist, from;constexpr Cost() : dist(0), from(-1) {}constexpr Cost(int dist) : dist(dist), from(-1) {}constexpr Cost(int dist, int to) : dist(dist), from(to) {}Cost operator+(const Cost& cost) const {return Cost(dist + cost.dist, cost.from);}bool operator<(const Cost& cost) const {if (dist != cost.dist) return dist < cost.dist;return from < cost.from;}};namespace std {template<> constexpr Cost numeric_limits<Cost>::max() {return Cost(numeric_limits<int>::max(), numeric_limits<int>::max());}}struct Edge {typedef Cost CostType;int from, to;Cost cost;Edge(int from, int to) : from(from), to(to), cost(0, from) {};Edge(int from, int to, int cost) : from(from), to(to), cost(cost, from) {};};int main() {int n, m, s, g;cin >> n >> m >> s >> g;AdjacencyList<Edge> graph(n);for (int i = 0; i < m; ++i) {int a, b, c;cin >> a >> b >> c;graph.addEdge(a, b, c);graph.addEdge(b, a, c);}cout << to_string(shortestPathTree(graph, g).shortestPathTree.getPath(s)) << endl;}