퍼즐 바닥은 PMU - 3678 (2 - 시간)

N 변수와 X1 배속은 ~ XN XN은, 각 변수의 가능한 값은 0 또는 1이다.

폼의 각 식의 M 방정식 주어  X- O P X- B = C , A, B는 가변 숫자 XaopXb = C, C는 숫자 0 또는 1, OP는 세의 XOR 비트 단위이고,이거나 가.

모든 방정식에 해당 그래서, 각 변수에 대한 법적 과제가 있는지 물어보십시오.

입력 형식

첫 번째 라인은 두 정수 N과 M. 포함

다음에 M 행, ABC 세 정수를 포함하는 각각의 행 및 비트 연산 (AND, OR, XOR 한).

출력 형식

출력이 존재하는 경우, 출력 "YES", 그렇지 않으면 "NO"

데이터 범위

1 N 1,000 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 문제, 변환 연산자가 결정 될 수있다

A는 [X] 일 수있다 들어 '구현 <X, [X], 심지어 X <A 가장자리 수 NOT 연통 에지 X>를 통해 X'구현> NOT 대한 (A [X] 및 [Y]) 사용자는 '<Y, X 및> 달성 될 두 에지 <x 연결할 필요가 A [X] OR A [Y]가'Y> 및 <Y ', x>에 <X, Y>'개의 모서리를 연결해야 실현

및, 또는 그래서, XOR 세 가지 작업은 다음과 같습니다 :

및 운영 :

a 및 b = 0 : A = 1이 경우, B = 0이 만족해야 B = 1, 그 다음이 만족해야하는 경우 = 0, 즉, <A, 1, B, 0>, <B, 1, A, 0>
A = B 및 1 :. A = 1, B = 1, 즉 <A, 0하는 ,. 1>, <B, 0, B ,. 1>
또는 동작 :

a 또는 b = 0 인 경우 : A = 0, B = 0, 즉 <는 ,. 1, A, 0>, <B는 ,. 1, B, 0> 
A 또는 B = 1 :. A = 0이 경우,이 반드시 만족 B = 1, B = 0, 다음, 즉 A = 0을 만족하여야있을 경우 : <A, 0, B ,. 1>, <B 0하는 ,. 1>
XOR 연산 :

배타적 B = 0, 다음의 네 가지 경우가 :
<A, 0, B는 A = 0 있다면, B = 0, 즉도 만족시켜야 0>
경우, B = 0, 다음, 즉, = 0이 만족시켜야을 : <B, 0, A, 0 >
경우, A = 1, 그 다음이 만족해야 B = 1, 즉 <A, 1, B 1>
B = 1, 다음, 즉, A = 1이 만족해야하는 경우 <B, 1 하는 ,. 1>
A = B의 XOR (1)는 다음 네 가지 경우 :.
A = 0 있다면, 즉 B = 1이 만족해야한다 : <A, 0, B는 1>
경우 B = 0, 다음을 만족해야 = 1, 즉 <B, 0, A, 1>
A = 1 다음, B = 0을가 만족해야하는 경우, 즉 <A, 1, B, 0>
B = 1, 그 다음이 만족해야하는 경우 = 0, 즉, <B, 1, A, 0>

사용법 #include <iostream> 
#INCLUDE <cstdio> 
#INCLUDE <알고리즘> 
#INCLUDE <CString을> 사용 스페이스 성병;
#DEFINE의 디버그 (X) COUT << << X << "\ n을"을 "버그 섹스";
#DEFINE IOS IOS :: sync_with_stdio (false)를 설정합니다 cin.tie (0) cout.tie (0)
 CONST의 INT maxn = 4e5 + (7) ; 
타입 정의 LL; INT의 N, m; 구조체 에지 
{ INT , NXT하는 단계; 
E} [maxn]; INT의 헤드 [maxn, TOT;
무효 추가는 ( int로 U를,

   




    


    E [ ++ 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] == DFN [X]) { 
        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 = 내가 ++ ) {
         int로 A, B, C를;  STR [ 10 ];
        // CIN 사항 >> >> >> B C >> STR; 
        scanf와 ( " % D % D % D % S ' , A, 및 B, C, STR);
        경우 (STR [ 0 ] == ' '
                (a하는 추가 +의 N); 
                (B, B 추가 + N)을; 
            } 다른 { 
                추가 (a + N, b); 
                (b 추가 + N, A); 
            } 
        } 다른  경우 STR ([ 0 ] == ' O ' ) {
             경우 (c의 == 1 ) { 
                (A, B 추가 + N)을; 
                (b하는 추가 +의 N)을; 
            } 다른 { 
                추가 (a + N, A);
                (b 추가 + N, b); 
            } 
        } 다른  경우 STR ([ 0 ] == ' X ' ) {
             경우 (c의 == 1 ) { 
                (A, B 추가 + N)을; 
                (b하는 추가 +의 N)을; 
                추가 (a + N, b); 
                (b 추가 + N, A); 
            } 다른 { 
                추가 (a, b); 
                추가 (b, a); 
                (a 추가 + N, B + N)을; 
                B (추가 + + N하는엔); 
            } 
        }     
    } 

    에 대해 ( int로 난 = 0 ; i가 N + N을 <; 내가 ++ ) {
         경우 (! tarjan (I) [I] DFN); 
    } 

    부울 플래그 = 1 ;
    위한 ( int로 I = 0 ; I <N은, 내가 ++ ) {
         경우 (C [I] == C [i가 + N]) { 
            플래그 = 0 ;
            휴식 ; 
        } 
    } 

    경우 (플래그) 풋 ( " YES " );
    다른풋 ( " NO " ); 

    반환  0 ; 
}

 

추천

출처www.cnblogs.com/DWVictor/p/11354998.html