C++ Library for Competitive Programming
/*
* @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;
}