This documentation is automatically generated by online-judge-tools/verification-helper
#include "graph/two_sat.hpp"#pragma once
#include "strongly_connected_components.hpp"
#include <optional>
class TwoSat {
public:
struct Variable {
private:
int idx;
Variable(int i) : idx(i) {}
public:
Variable operator!() const noexcept {
return Variable(idx ^ 1);
}
int index() const {
return idx / 2;
}
friend class TwoSat;
};
private:
std::vector<std::vector<int>> graph;
public:
TwoSat() : graph() {}
TwoSat::Variable add_variable() {
Variable var(graph.size());
graph.resize(graph.size() + 2, std::vector<int>());
return var;
}
std::vector<TwoSat::Variable> add_variables(int num) {
std::vector<TwoSat::Variable> vars;
vars.reserve(num);
for (int i = 0; i < num; ++i) {
vars.emplace_back(Variable((int) graph.size() + 2 * i));
}
graph.resize((int) graph.size() + 2 * num, std::vector<int>());
return vars;
}
// x or y
void add_clause(Variable x, Variable y) {
graph[(!x).idx].push_back(y.idx);
graph[(!y).idx].push_back(x.idx);
}
// x implies y
void implies(Variable x, Variable y) {
add_clause(!x, y);
}
void at_most_one(const std::vector<Variable> &vars) {
if (vars.size() <= 1) {
return;
}
std::vector<Variable> sum = add_variables((int) vars.size() - 1);
for (int i = 0; i < (int) sum.size(); ++i) {
implies(vars[i], sum[i]);
implies(sum[i], !vars[i + 1]);
}
for (int i = 0; i < (int) sum.size() - 1; ++i) {
implies(sum[i], sum[i + 1]);
}
}
std::optional<std::vector<bool>> solve() {
StronglyConnectedComponents scc(graph);
std::vector<bool> ans(graph.size() / 2, false);
for (int i = 0; i < (int) graph.size() / 2; ++i) {
if (scc[2 * i] == scc[2 * i + 1]) {
return std::nullopt;
}
if (scc[2 * i] > scc[2 * i + 1]) {
ans[i] = true;
}
}
return ans;
}
};#line 2 "graph/two_sat.hpp"
#line 2 "graph/strongly_connected_components.hpp"
#include <vector>
template <typename G>
class StronglyConnectedComponents {
std::vector<int> comp_id;
int comp_num;
public:
StronglyConnectedComponents(const G &g) : comp_id(g.size(), -1), comp_num(0) {
int now = 0;
std::vector<int> vs;
std::vector<int> ord(g.size(), -1);
std::vector<int> low(g.size(), -1);
const auto dfs = [&](const auto &dfs, int v) -> void {
vs.push_back(v);
ord[v] = now++;
low[v] = ord[v];
for (int u : g[v]) {
if (comp_id[u] != -1) {
continue;
}
if (ord[u] == -1) {
dfs(dfs, u);
}
low[v] = std::min(low[v], low[u]);
}
if (low[v] == ord[v]) {
while (true) {
int u = vs.back();
vs.pop_back();
comp_id[u] = comp_num;
if (u == v) {
break;
}
}
++comp_num;
}
};
for (int v = 0; v < (int) g.size(); ++v) {
if (ord[v] == -1) {
dfs(dfs, v);
}
}
for (int v = 0; v < (int) g.size(); ++v) {
comp_id[v] = comp_num - 1 - comp_id[v];
}
}
int comps() const {
return comp_num;
}
int operator[](int v) const {
assert(v >= 0 && v < (int) comp_id.size());
return comp_id[v];
}
std::vector<std::vector<int>> groups() const {
std::vector<std::vector<int>> ret(comp_num);
for (int v = 0; v < (int) comp_id.size(); ++v) {
ret[comp_id[v]].push_back(v);
}
return ret;
}
};
#line 4 "graph/two_sat.hpp"
#include <optional>
class TwoSat {
public:
struct Variable {
private:
int idx;
Variable(int i) : idx(i) {}
public:
Variable operator!() const noexcept {
return Variable(idx ^ 1);
}
int index() const {
return idx / 2;
}
friend class TwoSat;
};
private:
std::vector<std::vector<int>> graph;
public:
TwoSat() : graph() {}
TwoSat::Variable add_variable() {
Variable var(graph.size());
graph.resize(graph.size() + 2, std::vector<int>());
return var;
}
std::vector<TwoSat::Variable> add_variables(int num) {
std::vector<TwoSat::Variable> vars;
vars.reserve(num);
for (int i = 0; i < num; ++i) {
vars.emplace_back(Variable((int) graph.size() + 2 * i));
}
graph.resize((int) graph.size() + 2 * num, std::vector<int>());
return vars;
}
// x or y
void add_clause(Variable x, Variable y) {
graph[(!x).idx].push_back(y.idx);
graph[(!y).idx].push_back(x.idx);
}
// x implies y
void implies(Variable x, Variable y) {
add_clause(!x, y);
}
void at_most_one(const std::vector<Variable> &vars) {
if (vars.size() <= 1) {
return;
}
std::vector<Variable> sum = add_variables((int) vars.size() - 1);
for (int i = 0; i < (int) sum.size(); ++i) {
implies(vars[i], sum[i]);
implies(sum[i], !vars[i + 1]);
}
for (int i = 0; i < (int) sum.size() - 1; ++i) {
implies(sum[i], sum[i + 1]);
}
}
std::optional<std::vector<bool>> solve() {
StronglyConnectedComponents scc(graph);
std::vector<bool> ans(graph.size() / 2, false);
for (int i = 0; i < (int) graph.size() / 2; ++i) {
if (scc[2 * i] == scc[2 * i + 1]) {
return std::nullopt;
}
if (scc[2 * i] > scc[2 * i + 1]) {
ans[i] = true;
}
}
return ans;
}
};