建图如下
AND 1 a0->a1,b0->b1
AND 0 a1->b0,b1->a0
OR 1 a0->b1,b0->a1
OR 0 a1->a0,b1->b0
XOR 1 a0->b1,a1->b0,b1->a0,b0->a1
XOR 0 a0->b0,b0->a0,a1->b1,b1->a1
需要注意的是,如果a,b的值已经确定,比如说and 1 操作的时候,a,b的值都只能是1,那么需要加 a0->a1,b0->b1,这种加边跟平常的加边情况不同,具体请看 http://blog.sina.com.cn/s/blog_68629c7701010gf1.html
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <queue>
#define MAXN 10005
#define MAXM 4000005
#define INF 1000000000
using namespace std;
struct Edge
{
int v, next;
}edge[MAXM];
int n, m, e, head[MAXN];
int scc, index, fa[MAXN];
int instack[MAXN], low[MAXN], dfn[MAXN];
int st[MAXN], top;
void init()
{
e = scc = index = top = 0;
memset(head, -1, sizeof(head));
memset(instack, 0, sizeof(instack));
memset(dfn, 0, sizeof(dfn));
}
void insert(int x, int y)
{
edge[e].v = y;
edge[e].next = head[x];
head[x] = e++;
}
void tarjan(int u)
{
int v;
dfn[u] = low[u] = ++index;
st[++top] = u;
instack[u] = 1;
for(int i = head[u]; i != -1; i = edge[i].next)
{
v = edge[i].v;
if(!dfn[v])
{
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if(instack[v]) low[u] = min(low[u], dfn[v]);
}
if(dfn[u] == low[u])
{
scc++;
do
{
v = st[top--];
instack[v] = 0;
fa[v] = scc;
}while(v != u);
}
}
void build()
{
char s[15];
int x, y, w;
while(m--)
{
scanf("%d%d%d%s", &x, &y, &w, s);
x++; y++;
if(s[0] == 'A')
{
if(w == 0)
{
insert(x + n, y);
insert(y + n, x);
}
else
{
insert(x, x + n);
insert(y, y + n);
}
}
else if(s[0] == 'O')
{
if(w == 0)
{
insert(x + n, x);
insert(y + n, y);
}
else
{
insert(x, y + n);
insert(y, x + n);
}
}
else
{
if(w == 0)
{
insert(x + n, y + n);
insert(x, y);
insert(y, x);
insert(y + n, x + n);
}
else
{
insert(x, y + n);
insert(y, x + n);
insert(y + n, x);
insert(x + n, y);
}
}
}
}
bool check()
{
for(int i = 1; i <= n; i++)
if(fa[i] == fa[i + n]) return false;
return true;
}
void solve()
{
for(int i = 1; i <= 2 * n; i++)
if(!dfn[i]) tarjan(i);
if(check()) printf("YES\n");
else printf("NO\n");
}
int main()
{
while(scanf("%d%d", &n, &m) != EOF)
{
init();
build();
solve();
}
return 0;
}