1
#include
<
stdio.h
>
2
#include
<
string
.h
>
3
const
int
N
=
1000
+
10
;
4
#include
<
vector
>
5
using
namespace
std;
6
vector
<
int
>
edge[N
*
2
];
//
正向边
7
vector
<
int
>
iedge[N
*
2
];
//
逆向边
8
9
inline
void
addEdge(
int
s,
int
t)
10
{
11
edge[s].push_back(t);
12
iedge[t].push_back(s);
13
}
14
15
bool
visited[N
*
2
];
16
int
color[N
*
2
];
//
color[i]标记i点所属分量
17
vector
<
int
>
stack;
//
记录拓扑排序时的栈
18
void
dfs1(
int
p)
//
dfs1实际是在求拓扑图,拓扑排序后的信息逆序存于statck中
19
{
20
if
(visited[p]
==
true
)
return
;
21
visited[p]
=
true
;
22
int
sz
=
edge[p].size();
23
int
i;
24
for
(i
=
0
;i
<
sz;i
++
)
25
{
26
if
(
!
visited[edge[p][i]])
27
dfs1(edge[p][i]);
28
}
29
30
stack.push_back(p);
31
}
32
33
void
dfs2(
int
n,
int
group)
34
{
35
if
(visited[n]
==
true
)
return
;
36
visited[n]
=
true
;
37
int
i,sz
=
iedge[n].size();
38
for
(i
=
0
;i
<
sz;i
++
)
39
{
40
if
(
!
visited[iedge[n][i]])
41
dfs2(iedge[n][i],group);
42
}
43
color[n]
=
group;
44
}
45
void
two_SAT(
int
n)
//
n为点的个数
46
{
47
memset(visited,
false
,
sizeof
(visited));
48
int
i;
49
stack.clear();
50
for
(i
=
0
;i
<
n;i
++
)
51
{
52
if
(
!
visited[i])dfs1(i);
53
}
54
55
memset(visited,
false
,
sizeof
(visited));
56
57
int
group
=
0
;
58
int
sz
=
stack.size();
59
for
(i
=
sz
-
1
;i
>=
0
;i
--
)
60
{
61
if
(
!
visited[stack[i]])
62
dfs2(stack[i],group
++
);
63
}
64
65
//
printf("group = %d \n",group);
66
67
}
68
69
//
判断Ai,Ai'是否属于同一个强连通分量
70
bool
check(
int
m)
71
{
72
for
(
int
i
=
0
;i
<
m;i
++
)
73
if
(color[i]
==
color[i
+
m])
return
false
;
74
return
true
;
75
}
76
77
void
processAnd(
int
a,
int
b,
int
c,
int
n)
//
处理processAnd
78
{
79
if
(c
==
0
)
//
a,b不能同时取1
80
{
81
addEdge(a
+
n,b);
//
a=1 =>b=0
82
addEdge(b
+
n,a);
//
b=1 =>a=0
83
}
else
84
{
85
addEdge(a,a
+
n);
//
a = 0必不合法
86
addEdge(b,b
+
n);
//
b = 0必不合法
87
addEdge(a
+
n,b
+
n);
88
addEdge(b
+
n,a
+
n);
89
}
90
}
91
92
void
ProcessOr(
int
a,
int
b,
int
c,
int
n)
93
{
94
if
(c
==
0
)
95
{
96
addEdge(a
+
n,a);
//
a=1必不合法
97
addEdge(b
+
n,b);
//
b=1必不合法
98
addEdge(a,b);
99
addEdge(b,a);
100
}
101
else
102
{
103
addEdge(a,b
+
n);
//
a=0 => b = 1
104
addEdge(b,a
+
n);
//
b=0 => a = 1
105
}
106
}
107
108
inline
void
Processxor(
int
a,
int
b,
int
c,
int
n)
109
{
110
if
(c
==
1
)
111
{
112
addEdge(a,b
+
n);
113
addEdge(b
+
n,a);
114
addEdge(a
+
n,b);
115
addEdge(b,a
+
n);
116
}
117
else
118
{
119
addEdge(a
+
n,b
+
n);
120
addEdge(b
+
n,a
+
n);
121
addEdge(a,b);
122
addEdge(b,a);
123
}
124
}
125
int
main()
126
{
127
int
n,m;
128
int
a,b,c;
129
char
op[
10
];
130
131
while
(scanf(
"
%d%d
"
,
&
n,
&
m)
!=
EOF)
132
{
133
int
i;
134
for
(i
=
0
;i
<
2
*
n
+
1
;i
++
)
135
{
136
edge[i].clear();
137
iedge[i].clear();
138
}
139
while
(m
--
)
140
{
141
142
scanf(
"
%d%d%d%s
"
,
&
a,
&
b,
&
c,op);
143
if
(op[
0
]
==
'
A
'
)
144
processAnd(a,b,c,n);
145
else
146
if
(op[
0
]
==
'
O
'
)
147
ProcessOr(a,b,c,n);
148
else
149
if
(op[
0
]
==
'
X
'
)
150
Processxor(a,b,c,n);
151
152
}
153
154
two_SAT(
2
*
n);
155
156
if
(check(n))
157
printf(
"
YES\n
"
);
158
else
159
printf(
"
NO\n
"
);
160
161
}
162
163
return
0
;
164
}