2-SAT
lib/graph/two_sat.hpp
インクルード
#include "graph/two_sat.hpp"
クラス
| 名前 | 説明 |
|---|---|
two_sat |
2-SAT |
検証
依存するヘッダ(3)
-
グラフ表現 (list_graph / csr_graph)
lib/graph/graph.hpp -
強連結成分分解
lib/graph/scc.hpp -
CSR(Compressed Sparse Row)形式で隣接リストを保持する軽量な内部データ構造
lib/internal/internal_csr.hpp
検証プログラム(1)
-
test/yosupo/other/two_sat.test.cpp
test/yosupo/other/two_sat.test.cpp
実装
#pragma once
#include <vector>
#include "graph/scc.hpp"
#include "internal/internal_csr.hpp"
/// @brief 2-SAT
/// @complexity 変数数を $V$、節数を $C$ として構築 $O(V)$、求解 $O(V+C)$
struct two_sat {
/// @brief n変数の2-SATを構築する
/// @complexity $O(V)$
two_sat(int n) : _size(n) {}
/// @brief 節(iがf) OR (jがg)を追加する
/// @complexity 償却 $O(1)$
void add(int i, bool f, int j, bool g) {
i <<= 1, j <<= 1;
edges.emplace_back(i + (f ? 0 : 1), j + (g ? 1 : 0));
edges.emplace_back(j + (g ? 0 : 1), i + (f ? 1 : 0));
}
/// @brief 含意グラフの強連結成分番号を返す
/// @complexity $O(V+C)$
std::vector<int> solve() {
internal::Csr<int> G(_size * 2, edges);
auto res = scc(G);
return res;
}
/// @brief solveが返した成分番号が充足可能か確認する
/// @complexity $O(V)$
bool is_satisfy(const std::vector<int> &v) {
for (int i = 0; i < _size; ++i) {
if (v[i * 2] == v[i * 2 + 1]) return false;
}
return true;
}
/// @brief 成分番号から各変数の真偽値を構築する
/// @complexity $O(V)$
std::vector<bool> build(const std::vector<int> &v) {
std::vector<bool> res(_size);
for (int i = 0; i < _size; ++i) res[i] = v[i * 2] < v[i * 2 + 1];
return res;
}
private:
int _size;
std::vector<std::pair<int, int>> edges;
};