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万+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章