3678

1 /*
2 属于2SAT验证的题目。判断是否存在2SAT解
3 首先用scc算法缩图,判断只要没有对应的两点在一个强连通分量里面就算右解
4 构图的方法:
5 a & b = 1, 则a和b都必须为1,那么如果a选择了0,也必须转到1,所以a0->a1,对于b也是b0-b1
6 a和b只要有选择0,都必须重定向到1
7
8 a & b = 0,则a和b只要有1个是0就行了,所以如果b选择了1,则a必须选0,a选择1的时候,b必须选0
9 b1->a0,a1->b0
10
11 a | b = 1,则a和b中只要有1个1就行了,所以如果a选择了0,则b必须选择1,如果b选择了0,a必须选择1
12 a0->b1,b0->a1
13
14 ....其余依次类推
15
16 */
17 // include file
18 #include <cstdio>
19 #include <cstdlib>
20 #include <cstring>
21 #include <cmath>
22 #include <cctype>
23 #include <ctime>
24
25 #include <iostream>
26 #include <sstream>
27 #include <fstream>
28 #include <iomanip>
29 #include <bitset>
30 #include <strstream>
31
32 #include <algorithm>
33 #include <string>
34 #include <vector>
35 #include <queue>
36 #include <set>
37 #include <list>
38 #include <functional>
39
40 using namespace std;
41
42 // typedef
43 typedef long long LL;
44 typedef unsigned long long ULL;
45
46 //
47 #define read freopen("in.txt","r",stdin)
48 #define write freopen("out.txt","w",stdout)
49 #define FORi(a,b) for(int i=(a);i<(b);i++)
50 #define FORj(a,b) for(int j=(a);j<(b);j++)
51
52 #define FF(i,a) for(int i=0;i<(a);i+++)
53 #define FFD(i,a) for(int i=(a)-1;i>=0;i--)
54 #define Z(a) (a<<1)
55 #define Y(a) (a>>1)
56
57 const double eps = 1e-11;
58 const double Pi = acos(-1.0);
59
60 template<class T> inline T sqr(T a){return a*a;}
61 template<class T> inline T TMAX(T x,T y)
62 {
63 if(x>y) return x;
64 return y;
65 }
66 template<class T> inline T MMAX(T x,T y,T z)
67 {
68 return TMAX(TMAX(x,y),z);
69 }
70
71 // code begin
72 #define MAXN 2010
73
74 vector<int> G[MAXN];
75
76 int scc;
77 int cnt;
78 int used[MAXN];
79 int stk1[MAXN],top1;
80 int stk2[MAXN],top2;
81 int isin[MAXN];
82 int dfn[MAXN];
83 int id[MAXN];
84 int N,M;
85
86 void gabow_scc(int i)
87 {
88 used[i] = true;
89 stk1[top1++] = i;
90 stk2[top2++] = i;
91 dfn[i] = cnt++;
92 isin[i] = true;
93
94 FORj( 0,G[i].size() )
95 {
96 if(!used[ G[i][j] ])
97 {
98 gabow_scc(G[i][j]);
99 }
100 else if(isin[G[i][j]])
101 {
102 while(dfn[stk2[top2-1]]>dfn[G[i][j]])
103 top2--;
104 }
105 }
106
107 if(i==stk2[top2-1])
108 {
109 top2--;
110 int w;
111 do
112 {
113 w = stk1[--top1];
114 isin[w] = false;
115 id[w] = scc;
116 }while(w!=i);
117
118 scc++;
119 }
120 }
121
122 int main()
123 {
124 read;
125 write;
126 while(scanf("%d %d",&N,&M)!=-1)
127 {
128 FORi(0,2*N)
129 {
130 G[i].clear();
131 }
132
133 //建图
134 int a,b,c;
135 char op[5];
136 while(M--)
137 {
138 scanf("%d %d %d %s",&a,&b,&c,op);
139 // 2*a 2*b
140 // 2*a+1 2*b+1
141 switch(op[0])
142 {
143 case 'A':
144 if(c)
145 {
146 G[2*a].push_back(2*a+1);
147 G[2*b].push_back(2*b+1);
148 }
149 else
150 {
151 G[2*a+1].push_back(2*b);
152 G[2*b+1].push_back(2*a);
153 }
154 break;
155 case 'O':
156 if(c)
157 {
158 G[2*a].push_back(2*b+1);
159 G[2*b].push_back(2*a+1);
160 }
161 else
162 {
163 G[2*a+1].push_back(2*a);
164 G[2*b+1].push_back(2*b);
165 }
166 break;
167 case 'X':
168 if(c)
169 {
170 G[2*a].push_back(2*b+1);
171 G[2*b+1].push_back(2*a);
172 G[2*b].push_back(2*a+1);
173 G[2*a+1].push_back(2*b);
174 }
175 else
176 {
177 G[2*a].push_back(2*b);
178 G[2*b].push_back(2*a);
179 G[2*a+1].push_back(2*b+1);
180 G[2*b+1].push_back(2*a+1);
181 }
182 break;
183 }
184 }
185
186 // 运行gabow_scc
187 memset(used,0,sizeof(used));
188 memset(id,0,sizeof(used));
189 cnt = 1;
190 scc = 1;
191 top1 = top2 = 0;
192 FORi(0,2*N)
193 {
194 if(!used[i])
195 {
196 gabow_scc(i);
197 }
198 }
199
200 // 验证是否有2sat解
201 bool f = true;
202 FORi(0,N)
203 {
204 if( id[i*2]==id[i*2+1] )
205 {
206 f=false;
207 break;
208 }
209 }
210 if(f) printf("YES\n");
211 else printf("NO\n");
212 }
213 return 0;
214 }
posted @ 2011-02-28 18:08  AC2012  阅读(816)  评论(0编辑  收藏  举报