kyopro-lib

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

View on GitHub

:warning: Directed Eulerian path
(Mylib/Graph/EulerianPath/directed_eulerian_path.cpp)

Operations

Requirements

Notes

Problems

References

Code

#pragma once
#include <algorithm>
#include <map>
#include <optional>
#include <vector>

namespace haar_lib {
  class directed_eulerian_path {
    int n_, edges_;
    std::vector<std::map<int, int>> g_;
    std::vector<int> indeg_, outdeg_;

    void del(int i, int j) {
      if (g_[i][j] == 1)
        g_[i].erase(j);
      else
        --g_[i][j];
    }

    void dfs(int cur, std::vector<int> &path) {
      if (not g_[cur].empty()) {
        const int next = g_[cur].begin()->first;
        del(cur, next);
        dfs(next, path);
      }

      while (not g_[cur].empty()) {
        const int next = g_[cur].begin()->first;
        del(cur, next);
        std::vector<int> temp;
        dfs(next, temp);
        path.insert(path.end(), temp.begin(), temp.end());
      }

      path.push_back(cur);
    }

  public:
    directed_eulerian_path() {}
    directed_eulerian_path(int n) : n_(n), edges_(0), g_(n), indeg_(n), outdeg_(n) {}

    void add_edge(int i, int j) {
      ++g_[i][j];
      ++outdeg_[i];
      ++indeg_[j];
      ++edges_;
    }

    std::optional<std::vector<int>> eulerian_path() {
      int in = 0, out = 0, start = 0;

      for (int i = 0; i < n_; ++i) {
        const int d = outdeg_[i] - indeg_[i];
        if (std::abs(d) > 1) return std::nullopt;
        if (d == 1) {
          ++out;
          start = i;
        } else if (d == -1) {
          ++in;
        }
      }

      if (not((in == 0 and out == 0) or (in == 1 and out == 1))) return std::nullopt;

      std::vector<int> ret;

      dfs(start, ret);
      std::reverse(ret.begin(), ret.end());
      if ((int) ret.size() == edges_ + 1) {
        return ret;
      } else {
        return std::nullopt;
      }
    }
  };
}  // namespace haar_lib
#line 2 "Mylib/Graph/EulerianPath/directed_eulerian_path.cpp"
#include <algorithm>
#include <map>
#include <optional>
#include <vector>

namespace haar_lib {
  class directed_eulerian_path {
    int n_, edges_;
    std::vector<std::map<int, int>> g_;
    std::vector<int> indeg_, outdeg_;

    void del(int i, int j) {
      if (g_[i][j] == 1)
        g_[i].erase(j);
      else
        --g_[i][j];
    }

    void dfs(int cur, std::vector<int> &path) {
      if (not g_[cur].empty()) {
        const int next = g_[cur].begin()->first;
        del(cur, next);
        dfs(next, path);
      }

      while (not g_[cur].empty()) {
        const int next = g_[cur].begin()->first;
        del(cur, next);
        std::vector<int> temp;
        dfs(next, temp);
        path.insert(path.end(), temp.begin(), temp.end());
      }

      path.push_back(cur);
    }

  public:
    directed_eulerian_path() {}
    directed_eulerian_path(int n) : n_(n), edges_(0), g_(n), indeg_(n), outdeg_(n) {}

    void add_edge(int i, int j) {
      ++g_[i][j];
      ++outdeg_[i];
      ++indeg_[j];
      ++edges_;
    }

    std::optional<std::vector<int>> eulerian_path() {
      int in = 0, out = 0, start = 0;

      for (int i = 0; i < n_; ++i) {
        const int d = outdeg_[i] - indeg_[i];
        if (std::abs(d) > 1) return std::nullopt;
        if (d == 1) {
          ++out;
          start = i;
        } else if (d == -1) {
          ++in;
        }
      }

      if (not((in == 0 and out == 0) or (in == 1 and out == 1))) return std::nullopt;

      std::vector<int> ret;

      dfs(start, ret);
      std::reverse(ret.begin(), ret.end());
      if ((int) ret.size() == edges_ + 1) {
        return ret;
      } else {
        return std::nullopt;
      }
    }
  };
}  // namespace haar_lib
Back to top page