用add
加边, 最后调用solve
返回一个vector<int>
, 为空则无解, 否则为一组解.
struct TWO_SAT {
int siz;
std::vector<std::vector<int>> gra;
TWO_SAT(int size) : siz(size), gra(siz * 2 + 1) {}
// i -> x_i == 0, i + n -> x_i == 1
void add(int a, bool ta, int b, bool tb) {
gra[a + !ta * siz].push_back(b + tb * siz);
gra[b + !tb * siz].push_back(a + ta * siz);
}
std::vector<int> solve() {
std::vector<int> low(siz * 2 + 1), scc(siz * 2 + 1);
std::stack<int> sta;
int idx = 1, cnt = 0;
auto dfs = [&](int u, auto self) -> void {
low[u] = idx++;
int now = low[u];
sta.push(u);
for (auto v : gra[u]) {
if (!low[v])
self(v, self), low[u] = min(low[u], low[v]);
else if (!scc[v])
low[u] = min(low[u], low[v]);
}
if (low[sta.top()] >= now) {
cnt++;
while (sta.size() && low[sta.top()] >= now) {
auto t = sta.top();
sta.pop();
scc[t] = cnt;
}
}
};
for (int i = 1; i <= 2 * siz; i++) {
if (!low[i])
dfs(i, dfs);
}
std::vector<int> ans(siz + 1);
for (int i = 1; i <= siz; i++) {
if (scc[i] == scc[i + siz]) {
return std::vector<int>();
}
ans[i] = scc[i] > scc[i + siz];
}
return ans;
}
};
exp: P4782 【模板】2-SAT
void solve() {
int n, m;
cin >> n >> m;
TWO_SAT ts(n);
for (int i = 0; i < m; i++) {
int a, b, c, d;
cin >> a >> b >> c >> d;
ts.add(a, b, c, d);
}
auto res = ts.solve();
if (res.empty()) {
cout << "IMPOSSIBLE\n";
} else {
cout << "POSSIBLE\n";
for (int i = 1; i <= n; i++) {
cout << res[i] << ' ';
}
cout << '\n';
}
}