这道题算是2sat建图入门题。
把6种逻辑表达式转化为有向图
2-sat就是合取范式
1.a&&b=1就相当于是a和b两个析取式的合取范式,而a又可以写成a||a。
2.a&&b=0 ==》 !a||!b=1
3 a||b=1
4 a||b=0 ==》 !a&&!b=1 同1
5 a^b=1 ==》(!a&&b)||(a&&!b)=1数理逻辑的知识可以推出
(a||b)&&(!a||!b)
6 a^b=0 ==》(!a&&b)||(a&&!b)=0 ==》 (a||!b)&&(!a||b)=1
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <stdlib.h>
#include <stack>
#include <vector>
#include <string.h>
#include <queue>
#define msc(X) memset(X,-1,sizeof(X))
#define ms(X) memset(X,0,sizeof(X))
typedef long long LL;
using namespace std;
const int MAXN=2005;
const int MAXM=4e6+5;
struct _Edge
{
int to,next;
}edge[MAXM];
int tot,hd[MAXN];
void inti(void)
{
tot=0;
msc(hd);
}
void addedge(int u,int v)
{
edge[tot].to=v;
edge[tot].next=hd[u];
hd[u]=tot++;
}
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Index,top;
int scc;
bool Instack[MAXN];
void Tarjan(int u)
{
int v;
Low[u]=DFN[u]=++Index;
Stack[top++]=u;
Instack[u]=true;
for(int i=hd[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(!DFN[v]){
Tarjan(v);
if(Low[u]>Low[v]) Low[u]=Low[v];
}
else if(Instack[v]&&Low[u]>DFN[v])
Low[u]=DFN[v];
}
if(Low[u]==DFN[u]){
scc++;
do{
v=Stack[--top];
Instack[v]=false;
Belong[v]=scc;
}while(v!=u);
}
}
int main(int argc, char const *argv[])
{
int n,m;
while(scanf("%d %d",&n,&m)==2){
inti();
while(m--){
char s[5];
int a,b,c;
scanf("%d %d %d %s",&a,&b,&c,s);
if(s[0]=='A'){
if(c==1){// a&&b=1分解为a||a和b||b
addedge(a<<1,a<<1|1);//a<<1表示!a
addedge(b<<1,b<<1|1);
}
else{//a&&b=0即!a||!b
addedge(a<<1|1,b<<1);
addedge(b<<1|1,a<<1);
}
}
else if(s[0]=='O'){
if(c==1){//a||b=1
addedge(a<<1,b<<1|1);
addedge(b<<1,a<<1|1);
}
else{//a||b=0即!a&&!b=1
addedge(a<<1|1,a<<1);
addedge(b<<1|1,b<<1);
}
}
else{
if(c==1){//a^b=1分解(a||b)和(!a||!b)
addedge(a<<1,b<<1|1);
addedge(b<<1,a<<1|1);
addedge(a<<1|1,b<<1);
addedge(b<<1|1,a<<1);
}
else{//a^b=0即(a||!b)和(!a||b)
addedge(a<<1,b<<1);
addedge(b<<1|1,a<<1|1);
addedge(a<<1|1,b<<1|1);
addedge(b<<1,a<<1);
}
}
}
//强连通分量判断
ms(DFN);
ms(Instack);
Index=scc=top=0;
for(int i=0;i<2*n;i++)
if(!DFN[i]) Tarjan(i);
bool flg=false;
for(int i=0;i<n;i++)
if(Belong[i<<1]==Belong[i<<1|1])
{
flg=true;break;
}
puts(flg?"NO":"YES");
}
return 0;
}