Library

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

View the Project on GitHub jellc/Library

:heavy_check_mark: test/library-checker/two_sat.test.cpp

Depends on

Code

#define PROBLEM "https://judge.yosupo.jp/problem/two_sat"

#include "src/combinatorics/two_sat.hpp"

#include <cstdio>

int main() {
  char s[4];
  int n, m;
  scanf("%s%s%d%d", s, s, &n, &m);
  workspace::two_sat sol(n);
  while (m--) {
    int a, b;
    scanf("%d%d%s", &a, &b, s);
    if (a < 0)
      a = ~(-a - 1);
    else
      --a;
    if (b < 0)
      b = ~(-b - 1);
    else
      --b;
    sol.add_clause(a, b);
  }
  if (sol.run()) {
    printf("s SATISFIABLE\nv ");
    for (int i = 0; i < n; ++i) printf("%d ", sol[i] ? i + 1 : -(i + 1));
    printf("0\n");
  } else {
    printf("s UNSATISFIABLE\n");
  }
}
#line 1 "test/library-checker/two_sat.test.cpp"
#define PROBLEM "https://judge.yosupo.jp/problem/two_sat"

#line 2 "src/combinatorics/two_sat.hpp"

/**
 * @file two_sat.hpp
 * @brief 2-SAT
 */

#include <cassert>
#include <cstdint>
#include <vector>

namespace workspace {

// Linear time 2-SAT solver.
class two_sat : std::vector<std::vector<uint_least32_t>> {
 public:
  using size_type = uint_least32_t;

 private:
  using container_type = std::vector<std::vector<size_type>>;

  size_type *__tag = nullptr, *__top = nullptr;

  size_type node_size() const noexcept { return container_type::size(); }

  size_type index(size_type __x) const noexcept {
    return __x < ~__x ? __x << 1 : ~__x << 1 | 1;
  }

  bool dfs(size_type __s, size_type __d) noexcept {
    if (~__tag[__s]) return __tag[__s];

    __tag[ *__top++ = __s] = --__d;
    bool __ret = true;

    for (size_type __t : container_type::operator[](__s)) {
      if (!dfs(__t, __d)) __ret = false;
      if (__tag[__s] < __tag[__t]) __tag[__s] = __tag[__t];
    }

    if (__tag[__s ^ 1] == 1) __ret = false;

    if (__tag[__s] == __d) do
        __tag[*--__top] = __ret;
      while (*__top != __s);

    return __ret;
  }

 public:
  two_sat() noexcept {}

  two_sat(size_type __n) noexcept : container_type(__n << 1) {}

  ~two_sat() {
    delete[] __tag;
    delete[] __top;
  }

  using container_type::empty;

  size_type size() const noexcept { return node_size() >> 1; }

  size_type add_variable() noexcept {
    container_type::emplace_back(), container_type::emplace_back();
    return size() - 1;
  }

  auto add_variables(size_type __n) noexcept {
    container_type::reserve(node_size() + __n);
    typename container_type::value_type __vs(__n);

    for (auto &__v : __vs) __v = add_variable();
    return __vs;
  }

  void add_clause(size_type __x) noexcept {
    __x = index(__x);
    assert(__x < node_size());

    container_type::operator[](__x ^ 1).emplace_back(__x);
  }

  void add_clause(size_type __x, size_type __y) noexcept {
    __x = index(__x), __y = index(__y);
    assert(__x < node_size()), assert(__y < node_size());

    container_type::operator[](__x ^ 1).emplace_back(__y),
        container_type::operator[](__y ^ 1).emplace_back(__x);
  }

  template <class _Iterator>
  size_type atmost_one(_Iterator __first, _Iterator __last) noexcept {
    container_type::reserve(node_size() + std::distance(__first, __last) + 1);
    auto __any = add_variable();

    for (add_clause(~__any); __first != __last; ++__first) {
      auto __next = add_variable();
      add_clause(~__any, ~*__first), add_clause(~__any, __next),
          add_clause(~*__first, __next), __any = __next;
    }

    return __any;
  }

  template <class _Iterator>
  size_type exactly_one(_Iterator __first, _Iterator __last) noexcept {
    auto __any = atmost_one(__first, __last);
    add_clause(__any);
    return __any;
  }

  bool run() noexcept {
    delete[] __tag;
    delete[] __top;
    __tag = new size_type[node_size()], __top = new size_type[node_size()];

    std::fill_n(__tag, node_size(), -1);
    for (size_type __s = 0; __s != node_size(); ++__s) dfs(__s, -1);

    for (size_type __i = 0; __i != node_size(); __i += 2)
      if (__tag[__i] == __tag[__i ^ 1]) return false;

    return true;
  }

  bool operator[](size_type __i) const noexcept {
    __i = index(__i);
    assert(__i < node_size());

    return __tag[__i];
  }
};

}  // namespace workspace
#line 4 "test/library-checker/two_sat.test.cpp"

#include <cstdio>

int main() {
  char s[4];
  int n, m;
  scanf("%s%s%d%d", s, s, &n, &m);
  workspace::two_sat sol(n);
  while (m--) {
    int a, b;
    scanf("%d%d%s", &a, &b, s);
    if (a < 0)
      a = ~(-a - 1);
    else
      --a;
    if (b < 0)
      b = ~(-b - 1);
    else
      --b;
    sol.add_clause(a, b);
  }
  if (sol.run()) {
    printf("s SATISFIABLE\nv ");
    for (int i = 0; i < n; ++i) printf("%d ", sol[i] ? i + 1 : -(i + 1));
    printf("0\n");
  } else {
    printf("s UNSATISFIABLE\n");
  }
}
Back to top page