题意,给一些点,和边的值,和一些运算。
两个点经过运算是否可以满足边的值
比如 i-j 值是1 运算是 AND,那么 点i点j的值只能都是1.
就是求是否所有的点都满足这种情况。
典型的2-SAT问题。
将点s代表0,则s+n代表1。
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cmath>
#include <cstring>
#include <queue>
#include <set>
#include <vector>
#include <stack>
#include <map>
#include <iomanip>
#define PI acos(-1.0)
#define Max 1005
#define inf 1<<28
#define LL(x) (x<<1)
#define RR(x) (x<<1|1)
using namespace std;
struct kdq
{
int v,next;
} edge[1000005];
int head[Max];
int num=0;
int cntnum=0;
int dfn[Max],belong[Max],low[Max],instack[Max],sta[Max],index,top;
void add(int v,int to)
{
edge[num].v=to;
edge[num].next=head[v];
head[v]=num++;
}
void init()
{
memset(head,-1,sizeof(head));
memset(dfn,0,sizeof(dfn));
num=0;
cntnum=0;
index=0;
top=0;
}
int n,m;
void tarjan(int id)
{
dfn[id]=low[id]=index++;
instack[id]=1;
sta[top++]=id;
int temp=head[id];
while(temp!=-1)
{
int v=edge[temp].v;
if(!dfn[v])
{
tarjan(v);
if(low[v]<low[id])low[id]=low[v];
}
else if(instack[v]&&dfn[v]<low[id])
low[id]=dfn[v];
temp=edge[temp].next;
}
if(dfn[id]==low[id])
{
do
{
temp=sta[--top];
instack[temp]=0;
belong[temp]=cntnum;
}
while(temp!=id);
cntnum++;
}
}
int main()
{
cin>>n>>m;
init();
int s,t,c;
string op;
while(m--)
{
scanf("%d%d%d",&s,&t,&c);
cin>>op;
if(op=="AND")
{
if(c)//两个1
{
add(s+n,t+n);//1和1连接
add(t+n,s+n);
add(s,s+n);//表示只取后者
add(t,t+n);
}
else
{
add(s+n,t);//1和0
add(t+n,s);
}
}
else if(op=="OR")
{
if(!c)
{
add(s,t);//都是0
add(t,s);
add(s+n,s);//表示只取后者
add(t+n,t);
}
else
{
add(s,t+n);//0,1
add(t,s+n);
}
}
else
{
if(c)
{
add(s,t+n);//一个为0另一个必定为1
add(s+n,t);
add(t+n,s);
add(t,s+n);
}
else
{
add(s+n,t+n);//一个为0另一个必定为0,一个为1另一个必定为1
add(t+n,s+n);
add(s,t);
add(t,s);
}
}
}
for(int i=0; i<2*n; i++)
if(!dfn[i])tarjan(i);
bool flag=0;
for(int i=0; i<n; i++)
if(belong[i]==belong[i+n])
{
flag=1;
break;
}
if(flag)cout<<"NO"<<endl;
else cout<<"YES"<<endl;
return 0;
}