codeforces round 400 D The Door Problem 2-SAT

D. The Door Problem
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Moriarty has trapped n people in n distinct rooms in a hotel. Some rooms are locked, others are unlocked. But, there is a condition that the people in the hotel can only escape when all the doors are unlocked at the same time. There arem switches. Each switch control doors of some rooms, but each door is controlled byexactly two switches.

You are given the initial configuration of the doors. Toggling any switch, that is, turning it ON when it is OFF, or turning it OFF when it is ON, toggles the condition of the doors that this switch controls. Say, we toggled switch1, which was connected to room 1, 2 and 3 which were respectively locked, unlocked and unlocked. Then, after toggling the switch, they become unlocked, locked and locked.

You need to tell Sherlock, if there exists a way to unlock all doors at the same time.

Input

First line of input contains two integers n andm (2 ≤ n ≤ 105,2 ≤ m ≤ 105) — the number of rooms and the number of switches.

Next line contains n space-separated integersr1, r2, ..., rn (0 ≤ ri ≤ 1) which tell the status of room doors. The i-th room is locked ifri = 0, otherwise it is unlocked.

The i-th of next m lines contains an integer xi (0 ≤ xi ≤ n) followed byxi distinct integers separated by space, denoting the number of rooms controlled by thei-th switch followed by the room numbers that this switch controls. It is guaranteed that the room numbers are in the range from1 to n. It is guaranteed that each door is controlled by exactly two switches.

Output

Output "YES" without quotes, if it is possible to open all doors at the same time, otherwise output "NO" without quotes.

Examples
Input
3 3
1 0 1
2 1 3
2 1 2
2 2 3
Output
NO
Input
3 3
1 0 1
3 1 2 3
1 2
2 1 3
Output
YES
Input
3 3
1 0 1
3 1 2 3
2 1 2
1 3
Output
NO
Note

In the second example input, the initial statuses of the doors are [1, 0, 1] (0 means locked, 1 — unlocked).

After toggling switch 3, we get [0, 0, 0] that means all doors are locked.

Then, after toggling switch 1, we get [1, 1, 1] that means all doors are unlocked.

It can be seen that for the first and for the third example inputs it is not possible to make all doors unlocked.


/*
    題目描述:有n道門,m個開關,每道門由m個開關中的兩個控制,若門的狀態是0(關),那麼改變控制這道門的一個開關之後,門的
         狀態就變爲1(開),若門的狀態是1(開),那麼改變控制這道門的一個開關之後,門的狀態就變爲0(關)。
           現已知n道門的初始狀態,以及m個開關分別控制哪些門,問能不能通過按下某些開關,使得全部門的狀態都變爲1。
                        
    思路:看到每道門恰好兩個開關控制,想到2-SAT解決。對於每道門,已知控制這道門的開關是x,y,如果這道門的初始狀態爲1,那麼
       加入語句(!x ∨ y)∧(x∨!y),表示x和y必須同開同關,如果這道門的初始狀態爲0,那麼加入語句(!x ∨ !y)∧(x∨y),表示x和y必須
       一開一關,跑2-SAT得到結果
            
    收穫:對於一個條件,不一定要用一個帶有∨ 的語句來反映,可以用以∧連接的多個帶∨語句來表示
*/
#pragma warning(disable:4786)
#pragma comment(linker, "/STACK:102400000,102400000")
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<bitset>
#define LL long long
#define FOR(i,f_start,f_end) for(int i=f_start;i<=f_end;++i)
#define mem(a,x) memset(a,x,sizeof(a))
#define lson l,m,x<<1
#define rson m+1,r,x<<1|1
using namespace std;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double PI = acos(-1.0);
const double eps=1e-6;
const int maxn = 1e5 + 5;
vector<int>v[maxn];
int door[maxn];
struct TwoSat
{
    int n ;
    vector<int>G[maxn * 2];
    bool mark[maxn * 2];
    int S[maxn * 2] , c;

    bool dfs(int x)
    {
        if(mark[x^1])      return false;
        if(mark[x])         return true;
        mark[x] = true;
        S[c++] = x;
        for(int i = 0 ; i < G[x].size()  ; i++){
            if(!dfs(G[x][i]))       return false;
        }
        return true;
    }

    void init(int n)
    {
        this -> n = n;
        for(int i = 0 ; i < n * 2 ; i++){
            G[i].clear();
        }
        mem(mark , 0);
    }

    void add_clause(int x , int xval , int y , int yval)
    {
        x = x * 2 + xval;
        y = y * 2 + yval;
        G[x ^ 1].push_back(y);
        G[y ^ 1].push_back(x);
    }

    bool solve()
    {
        for(int i = 0 ; i < n * 2 ; i+=2){
            if(!mark[i] && !mark[i + 1]){
                c = 0;
                if(!dfs(i)){
                    while(c > 0)        mark[S[--c]] = false;       //已經嘗試過把i標記爲true,然而不行,那麼在嘗試將i+1標記爲真時,先把i的影響消掉
                    if(!dfs(i + 1))        return false;
                }
            }
        }
        return true;
    }
}twosat;
int main()
{
    int n , m , x , y;
    scanf("%d %d" , &n, &m);
    for(int i = 0 ; i< n ; i++){
        scanf("%d" , &door[i]);
    }
    for(int i = 0 ; i < m ; i++){
        scanf("%d" , &x);
        for(int j = 0 ; j<x ; j++){
            scanf("%d" , &y);
            v[y - 1].push_back(i);
        }
    }
    twosat.init(m);
    for(int i = 0 ; i < n ; i++){
        if(door[i]){
            twosat.add_clause(v[i][0] , 0 , v[i][1] , 1);
            twosat.add_clause(v[i][0] , 1 , v[i][1] , 0);
        }
        else{
            twosat.add_clause(v[i][0] , 0 , v[i][1] , 0);
            twosat.add_clause(v[i][0] , 1 , v[i][1] , 1);
        }
    }
    bool ans = twosat.solve();
    if(ans)         puts("YES");
    else             puts("NO");
    return 0;
}



發佈了138 篇原創文章 · 獲贊 24 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章