cp-library

C++ Library for Competitive Programming

View the Project on GitHub emthrm/cp-library

:heavy_check_mark: その他/2-SAT
(test/misc/2-sat.test.cpp)

Depends on

Code

/*
 * @title その他/2-SAT
 *
 * verification-helper: PROBLEM https://judge.yosupo.jp/problem/two_sat
 */

#include <iostream>
#include <string>
#include <vector>

#include "emthrm/misc/2-sat.hpp"

int main() {
  std::string p, cnf;
  int n, m;
  std::cin >> p >> cnf >> n >> m;
  emthrm::TwoSat two_sat(n);
  while (m--) {
    int a, b, zero;
    std::cin >> a >> b >> zero;
    if (a < 0) {
      a = two_sat.negate(-a - 1);
    } else {
      --a;
    }
    if (b < 0) {
      b = two_sat.negate(-b - 1);
    } else {
      --b;
    }
    two_sat.add_or(a, b);
  }
  const std::vector<bool> ans = two_sat.build();
  std::cout << "s ";
  if (ans.empty()) {
    std::cout << "UNSATISFIABLE\n";
    return 0;
  }
  std::cout << "SATISFIABLE\nv ";
  for (int i = 0; i < n; ++i) {
    std::cout << (i + 1) * (ans[i] ? 1 : -1) << ' ';
  }
  std::cout << "0\n";
  return 0;
}
#line 1 "test/misc/2-sat.test.cpp"
/*
 * @title その他/2-SAT
 *
 * verification-helper: PROBLEM https://judge.yosupo.jp/problem/two_sat
 */

#include <iostream>
#include <string>
#include <vector>

#line 1 "include/emthrm/misc/2-sat.hpp"



#include <algorithm>
#line 6 "include/emthrm/misc/2-sat.hpp"

namespace emthrm {

struct TwoSat {
  explicit TwoSat(const int n)
      : n(n), graph(n << 1), rgraph(n << 1), is_visited(n << 1), ids(n << 1) {
    order.reserve(n << 1);
  }

  int negate(const int x) const { return (n + x) % (n << 1); }

  void add_or(const int x, const int y) {
    graph[negate(x)].emplace_back(y);
    graph[negate(y)].emplace_back(x);
    rgraph[y].emplace_back(negate(x));
    rgraph[x].emplace_back(negate(y));
  }

  void add_if(const int x, const int y) { add_or(negate(x), y); }

  void add_nand(const int x, const int y) { add_or(negate(x), negate(y)); }

  void set_true(const int x) { add_or(x, x); }

  void set_false(const int x) { set_true(negate(x)); }

  std::vector<bool> build() {
    std::fill(is_visited.begin(), is_visited.end(), false);
    std::fill(ids.begin(), ids.end(), -1);
    order.clear();
    for (int i = 0; i < (n << 1); ++i) {
      if (!is_visited[i]) dfs(i);
    }
    for (int i = (n << 1) - 1, id = 0; i >= 0; --i) {
      if (ids[order[i]] == -1) rdfs(order[i], id++);
    }
    std::vector<bool> res(n);
    for (int i = 0; i < n; ++i) {
      if (ids[i] == ids[negate(i)]) return {};
      res[i] = ids[negate(i)] < ids[i];
    }
    return res;
  }

 private:
  const int n;
  std::vector<std::vector<int>> graph, rgraph;
  std::vector<bool> is_visited;
  std::vector<int> ids, order;

  void dfs(const int ver) {
    is_visited[ver] = true;
    for (const int dst : graph[ver]) {
      if (!is_visited[dst]) dfs(dst);
    }
    order.emplace_back(ver);
  }

  void rdfs(const int ver, const int cur_id) {
    ids[ver] = cur_id;
    for (const int dst : rgraph[ver]) {
      if (ids[dst] == -1) rdfs(dst, cur_id);
    }
  }
};

}  // namespace emthrm


#line 12 "test/misc/2-sat.test.cpp"

int main() {
  std::string p, cnf;
  int n, m;
  std::cin >> p >> cnf >> n >> m;
  emthrm::TwoSat two_sat(n);
  while (m--) {
    int a, b, zero;
    std::cin >> a >> b >> zero;
    if (a < 0) {
      a = two_sat.negate(-a - 1);
    } else {
      --a;
    }
    if (b < 0) {
      b = two_sat.negate(-b - 1);
    } else {
      --b;
    }
    two_sat.add_or(a, b);
  }
  const std::vector<bool> ans = two_sat.build();
  std::cout << "s ";
  if (ans.empty()) {
    std::cout << "UNSATISFIABLE\n";
    return 0;
  }
  std::cout << "SATISFIABLE\nv ";
  for (int i = 0; i < n; ++i) {
    std::cout << (i + 1) * (ans[i] ? 1 : -1) << ' ';
  }
  std::cout << "0\n";
  return 0;
}
Back to top page