Nyaan's Library

This documentation is automatically generated by online-judge-tools/verification-helper

View on GitHub

:heavy_check_mark: shortest-path/dijkstra-abstruct.hpp

Verified with

Code

#pragma once

#include <functional>
#include <map>
#include <queue>
#include <utility>
#include <vector>
using namespace std;

// start : 始点
// goal  : 到達した終点 (goal が無い/着かない場合 Index{})
// dist  : start - goal 間の距離
// reachable : goal に着いたか?を意味する bool
// path  : start から goal へのパス (reachable = false の場合は空)
// mp    : mp[頂点] = (最短距離, 1 つ前の頂点) を管理する map
template <typename Index, typename Cost>
struct DijkstraResult {
  Index start, goal;
  Cost dist;
  bool reachable;
  map<Index, pair<Cost, Index>> mp;
  vector<Index> path;

  DijkstraResult(const Index& s, const Index& g, Cost d, bool r,
                 const map<Index, pair<Cost, Index>>& m)
      : start(s), goal(g), dist(d), reachable(r), mp(m) {
    if (reachable) {
      for (Index c = g; c != s; c = mp[c].second) path.push_back(c);
      path.push_back(s);
      reverse(begin(path), end(path));
    }
  }
};

// 引数 f は (頂点 v, s-v 間の距離, 関数 g) を引数に取る
// f の内部で g(次の頂点 w, s-w 間の距離) を呼び出して使う
//
// 返り値は DijkstraResult<Index, Cost> を返す
//
// goal は lambda 式 or 値 を渡せる, goal が複数ある場合に対応している
// (始点が複数ある場合は超頂点を使うことにする)
template <typename Index, typename Cost, bool has_goal = true>
DijkstraResult<Index, Cost> dijkstra_abstruct(
    const function<void(Index, Cost, function<void(Index, Cost)>)>& f,
    const Index& start, const function<bool(Index)>& is_goal) {
  using P = pair<Cost, Index>;

  map<Index, P> d;
  priority_queue<P, vector<P>, greater<P>> Q;
  d[start] = P(0, Index{});
  Q.emplace(0, start);

  while (!Q.empty()) {
    auto [u, t] = Q.top();
    Q.pop();
    if (d[t].first != u) continue;
    if constexpr (has_goal) {
      if (is_goal(t)) return {start, t, u, true, d};
    }
    auto add = [&](Index nt, Cost nu) {
      if (d.count(nt) == 0 or nu < d[nt].first) {
        d[nt] = P(nu, t);
        Q.emplace(nu, nt);
      }
    };
    f(t, u, add);
  }
  return {start, Index{}, Cost{}, false, d};
}

// 引数 f は (頂点 v, s-v 間の距離, 関数 g) を引数に取る
// f の内部で g(次の頂点 w, s-w 間の距離) を呼び出して使う
//
// 返り値は DijkstraResult<Index, Cost> を返す
//
// goal は lambda 式 or 値 を渡せる, goal が複数ある場合に対応している
// (始点が複数ある場合は超頂点を使うことにする)
template <typename Index, typename Cost, bool has_goal = true>
DijkstraResult<Index, Cost> dijkstra_abstruct(
    const function<void(Index, Cost, function<void(Index, Cost)>)>& f,
    const Index& start, const Index& goal = Index{}) {
  const function<bool(Index)> is_goal = [&goal](Index i) -> bool {
    return i == goal;
  };
  return dijkstra_abstruct<Index, Cost, has_goal>(f, start, is_goal);
}
#line 2 "shortest-path/dijkstra-abstruct.hpp"

#include <functional>
#include <map>
#include <queue>
#include <utility>
#include <vector>
using namespace std;

// start : 始点
// goal  : 到達した終点 (goal が無い/着かない場合 Index{})
// dist  : start - goal 間の距離
// reachable : goal に着いたか?を意味する bool
// path  : start から goal へのパス (reachable = false の場合は空)
// mp    : mp[頂点] = (最短距離, 1 つ前の頂点) を管理する map
template <typename Index, typename Cost>
struct DijkstraResult {
  Index start, goal;
  Cost dist;
  bool reachable;
  map<Index, pair<Cost, Index>> mp;
  vector<Index> path;

  DijkstraResult(const Index& s, const Index& g, Cost d, bool r,
                 const map<Index, pair<Cost, Index>>& m)
      : start(s), goal(g), dist(d), reachable(r), mp(m) {
    if (reachable) {
      for (Index c = g; c != s; c = mp[c].second) path.push_back(c);
      path.push_back(s);
      reverse(begin(path), end(path));
    }
  }
};

// 引数 f は (頂点 v, s-v 間の距離, 関数 g) を引数に取る
// f の内部で g(次の頂点 w, s-w 間の距離) を呼び出して使う
//
// 返り値は DijkstraResult<Index, Cost> を返す
//
// goal は lambda 式 or 値 を渡せる, goal が複数ある場合に対応している
// (始点が複数ある場合は超頂点を使うことにする)
template <typename Index, typename Cost, bool has_goal = true>
DijkstraResult<Index, Cost> dijkstra_abstruct(
    const function<void(Index, Cost, function<void(Index, Cost)>)>& f,
    const Index& start, const function<bool(Index)>& is_goal) {
  using P = pair<Cost, Index>;

  map<Index, P> d;
  priority_queue<P, vector<P>, greater<P>> Q;
  d[start] = P(0, Index{});
  Q.emplace(0, start);

  while (!Q.empty()) {
    auto [u, t] = Q.top();
    Q.pop();
    if (d[t].first != u) continue;
    if constexpr (has_goal) {
      if (is_goal(t)) return {start, t, u, true, d};
    }
    auto add = [&](Index nt, Cost nu) {
      if (d.count(nt) == 0 or nu < d[nt].first) {
        d[nt] = P(nu, t);
        Q.emplace(nu, nt);
      }
    };
    f(t, u, add);
  }
  return {start, Index{}, Cost{}, false, d};
}

// 引数 f は (頂点 v, s-v 間の距離, 関数 g) を引数に取る
// f の内部で g(次の頂点 w, s-w 間の距離) を呼び出して使う
//
// 返り値は DijkstraResult<Index, Cost> を返す
//
// goal は lambda 式 or 値 を渡せる, goal が複数ある場合に対応している
// (始点が複数ある場合は超頂点を使うことにする)
template <typename Index, typename Cost, bool has_goal = true>
DijkstraResult<Index, Cost> dijkstra_abstruct(
    const function<void(Index, Cost, function<void(Index, Cost)>)>& f,
    const Index& start, const Index& goal = Index{}) {
  const function<bool(Index)> is_goal = [&goal](Index i) -> bool {
    return i == goal;
  };
  return dijkstra_abstruct<Index, Cost, has_goal>(f, start, is_goal);
}
Back to top page