思路:典型的2-SAT合理性判定模板题
分类:
1、a&b=0: 若a为1,则b必为0; 若b为1,则a必为0
2、a&b=1: 若a为0,则a必为1; 若b为0,则b必为1 //这个地方需要理解一下
3、a|b=0: a=1则a必为0; b=1则b必为0
4、a|b=1: a=0则b必为1; b=0则a必为1
5、a^b=1: a=0,则b=1;a=1则b=0;b=0,则a=1;b=1,a=0
6、a^b=0: a=0,则b=0;a=1,则b=1;b=0,则a=0;b=1,则a=1
//2-SAT合理性判定
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<string.h>
#include<stack>
using namespace std;
const int N = 2e3 + 10;
const int M = 1e7 + 10;
int head[N], tot;
int n, m;
int sccno[N], scc_cnt, dfn[N], low[N], idx;
stack<int>st;
struct Edge {
int to;
int nxt;
}e[M];
void add(int u, int v) {
e[++tot].to = v;
e[tot].nxt = head[u];
head[u] = tot;
}
void dfs(int u) {
st.push(u);
dfn[u] = low[u] = ++idx;
for (int v, i = head[u]; i != -1; i = e[i].nxt) {
v = e[i].to;
if (!dfn[v]) {
dfs(v);
low[u] = min(low[u], low[v]);
}
else if (!sccno[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
scc_cnt++;
while (1) {
int x = st.top();
st.pop();
sccno[x] = scc_cnt;
if (x == u)break;
}
}
}
bool find_scc() {
memset(sccno, 0, sizeof(sccno));
memset(dfn, 0, sizeof(dfn));
memset(low, 0, sizeof(low));
scc_cnt = idx = 0;
for (int i = 1; i <= 2 * n + 1; i++) {
if (!dfn[i])dfs(i);
}
for (int i = 1; i <= n; i++) {
if (sccno[i] == sccno[i + n])return false;
}
return true;
}
int main() {
scanf("%d%d", &n, &m);
memset(head, -1, sizeof(head));
tot = 0;
char op[10];
for (int a, b, c, i = 1; i <= m; i++) {
scanf("%d%d%d%s", &a, &b, &c, op);
a++;
b++;
if (op[0] == 'A') {
if (c) { //a&b==1: a==0,则a必为1;b==0,则b必为1
add(a + n, a);
add(b + n, b);
}
else { //a&b==0: a==1则b必为0;b==1则a必为0
add(a, b + n);
add(b, a + n);
}
}
else if (op[0] == 'O') {
if (c) { //a|b==1: a==0则b必为1;b==0则a必为1
add(a + n, b);
add(b + n, a);
}
else { //a|b==0: a==1,则a必为0;b==1,则b必为0
add(a, a + n);
add(b, b + n);
}
}
else if (op[0] == 'X') {
if (c) { //a^b==1: a==0,则b==1;a==1则b==0;b==0,则a==1;b==1,a==0
add(a + n, b);
add(a, b + n);
add(b + n, a);
add(b, a + n);
}
else { //a^b==0: a==0,则b==0;a==1,则b==1;b==0,则a==0;b==1,则a==1
add(a + n, b + n);
add(a, b);
add(b + n, a + n);
add(b, a);
}
}
}
printf(find_scc() ? "YES\n" : "NO\n");
return 0;
}