N変数とX1 X1〜XN XN、各変数の可能な値は0又は1です。
フォームの各式、M方程式所与 X- A O P X- B = C、Bが可変数であるXaopXb = C、Cは、数0又は1、OPは、3つのXORビット単位であり、又はありますA。
すべての式が真であるように、各変数への法的な割り当てがあるかどうかを確認して下さい。
入力形式
最初の行は二つの整数N及びMを含有します
次のM行、ABC三つの整数を含む各列、及びビット演算(AND、OR、XOR 1)。
出力フォーマット
出力、存在する場合、出力「YES」、そうでない場合は「NO」
データ範囲
1 ≤ N ≤ 1000年 1≤N≤1000、
1 ≤ M ≤ 10 6 1≤M≤106
サンプル入力:
4 4
0 1 1 AND 1 2 1 OR 3 2 0 AND 3 0 0 XOR
出力例:
YES
アイデア:質問の意味、問題は2-SATの問題であり、変換演算子は、判断することができます
[x]は、することができるためではない([X]およびA [Y])のために '<実施実現、X、[x]は、偶数<X、X>通信エッジを介してX Edgeのできない' を>あなたは '<Y、X及び>達成され、二つのエッジ<X接続する必要がある[X]または[Y]が ' Y>とを<Y'、X>から<X、Y>' 2つのエッジを接続するために必要実現
以下のためのように、または、XORの3つの動作は以下のとおりです。
そして、操作:
及びb = 0:= 1である場合、B = 0が満たさなければならない; B = 1なら、すなわち、= 0が満たさなければならない:<1、B、 0>、<B、1、 0>
A = Bと1:A = 1、B = 1、すなわち:<A、0、1、。>、<B、0、B ,. 1>
又は操作:
またはb = 0の場合:= 0、B = 0、すなわち<,. 1、A、0>、<B ,. 1、B、0>
。AまたはB = 1:= 0がある場合、そこ必要満たすB = 1; b = 0であれば、= 0、つまり存在満たさなければならない:<A、0、B ,. 1>、<B、0、1、。>
XOR演算を:
XOR b = 0で、以下の4例:
= 0の場合、B = 0が満たさなければならない、すなわち:<0、B、 0>
B = 0の場合、すなわち、= 0が満たさなければなりません。 <B、0、0 >
= 1の場合、すなわち、B = 1、が満たさなければならない:<1、B 1>を
、B = 1の場合、すなわち、= 1が満たさなければならない:<B、1 、,. 1>
A = B XOR 1、以下4例:
<0、B = 0の場合、B = 1、すなわちそこに満足しなければならない 1>
= 0 bであれば、満たされなければなりません= 1、すなわち、<B、0、 1>
B = 0、すなわち満足しなければならない= 1であれば、そこ:<1、B、 0>
B = 1の場合、次に、すなわち、= 0が満たさなければなりません。 <B、1、 0>
#include <iostreamの> する#include <cstdioを> する#include <アルゴリズム> の#include <CStringの> 使用して名前空間STD。 #defineデバッグ(x)はcoutの<< << X << "\ n"を"バグ性交"。 #define IOS IOS :: sync_with_stdio(偽)、cin.tie(0)、cout.tie(0) CONST INT MAXN = 4E5 + 7 。 typedefの長い長いLL。INTのN、M。構造体の縁 { INT 、NXTに、 } E [MAXN]。int型のヘッド[MAXN]、TOT; 無効アドオン(int型のuを、 ++ TOT] .TO = V。 E [TOT] .nxt = 頭部[U]。 ヘッド[U]は = TOTを、 } INT DFN [MAXN]、低[MAXN]、NUM、inStack [MAXN]。 INTのスタック[MAXN]、トップ、CNT、C [MAXN]。 ボイド tarjan(INT X){ [X] DFN =低[X] = ++ NUM。 [スタック ++トップ] = xを、inStack [X] = 真。 以下のために(int型 ; I I = I =ヘッド[X] {E [I] .nxt) INT Y = E [I] .TO。 もし(DFN [Y] == 0 ){ tarjan(Y)。 低[X] = 分(低[x]は、低[Y])。 } そう であれば(inStack [Y]){ 低い[X] = 分(低[x]は、低[Y])。 } } もし(低[X] == {[X] DFN) CNT ++ 。 int型のZ; { Zは = [top--スタック]。 inStack [Z] = 偽。 C [Z] = CNT。 } 一方(Z =!X)。 } } int型(主 INT ARGC、チャー CONST * ARGV []) { // CIN >> N >> M。 scanf関数(" %d個の%のD "、&N、&M)。 以下のために(int型私= 1 ; I <= M; iが++ ){ int型、B、C。チャー STR [ 10 ]。 // cinを>> A >> B >> C >> STR。 scanf関数(" %D%D%D%S "、&、&B、&C、STR)。 もし(STR [ 0 ] == ' A ' (追加 +のN)。 (B、B追加 + n)を。 } 他{ 追加(A + N、B)。 (Bを追加 + N、A)。 } } そう であれば(STR [ 0 ] == ' O ' ){ 場合(Cの== 1 ){ (B追加 + n)を。 (B、追加 +のN)。 } 他{ 追加(A +N、A)。 (B追加 + B、N)。 } } そう であれば(STR [ 0 ] == ' X ' ){ 場合(C == 1 ){ (B追加 + n)を。 (B、追加 +のN)。 追加(A + N、B)。 (Bを追加 + N、A)。 } 他{ 追加(A、B)。 (B、A)を加えます。 (A追加 + N、B + N)。 (B追加、+ N A +N); } } } のための(int型 I = 0 ; iが<N + N; iが++ ){ 場合(!tarjan(I)DFN [I])。 } ブールフラグ= 1 。 以下のために(int型 i = 0 ; iがn <; iは++ ){ もし(C [I] == C [iが+ N]){ フラグ = 0 。 破ります; } } もし(フラグ)プット(" YES " ); 他プット(" NO " ); リターン 0 ; }