Codeforces Round #400 (Div. 1 + Div. 2, combined)D. The Door Problem【2-sat Tarjan+思维建图】

来源:互联网 发布:战地2网络对战平台 编辑:程序博客网 时间:2024/05/01 17:44

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 are m switches. Each switch control doors of some rooms, but each door is controlled by exactly 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 switch 1, which was connected to room 12 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 and m (2 ≤ n ≤ 1052 ≤ m ≤ 105) — the number of rooms and the number of switches.

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

The i-th of next m lines contains an integer xi (0 ≤ xi ≤ n) followed by xi distinct integers separated by space, denoting the number of rooms controlled by the i-th switch followed by the room numbers that this switch controls. It is guaranteed that the room numbers are in the range from 1to 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 31 0 12 1 32 1 22 2 3
output
NO
input
3 31 0 13 1 2 31 22 1 3
output
YES
input
3 31 0 13 1 2 32 1 21 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个开关,对于这N个监狱的开关初始状态已知(0表示关,1表示开);

对于M个开关,每个开关会控制很多监狱的开关,只要按下,对应0会变成1,1会变成0。

我们需要判定是否按下一些开关能够使得最终状态全是1.

保证每个监狱只被两个开关控制。


思路:


1、观察到题干说明,保证每个监狱的状态只受到两个开关的控制。

那么我们将M个开关开成M个点,那么对于每个点来讲,有两种状态:①按下了,②没按下,那么M个点再拆分出来M个点,共计2M个点,其中M个点代表这个开关按下了,另外M个点代表这哥开关没按下,那么对应问题就变成了2-sat模型。


2、考虑找到矛盾边进行建图判定:
①对于a【i】==1(初始状态为开)的监狱,那么对应控制这个监狱的两个开关,要么全按下(抵消掉了,最终结果还是1),要么全没有按下(保持不变);

那么矛盾边就是:

一个开关开了,另一个开关关了的两种可能;

②对于a【i】==0(初始状态为关)的监狱,那么对应控制这个监狱的两个开关,肯定要有一个开,另外一个关。

那么矛盾边就是:

两个开关都开了,或者是两个开关都没按的情况。


3、那么问题按照上述过程建立矛盾边,之后Tarjan强联通判断有没有color【i】==color【i+n】的矛盾情况出现即可。


Ac代码:


#include<stdio.h>#include<string.h>#include<vector>using namespace std;struct Edge{    int from,to,next;}e[15000000];int stack[500000];int color[500000];int dfn[500000];int low[500000];int vis[500000];int head[505000];vector<int >s[120050];int num[120050];int a[120050];int cont,cnt,sig,tt;void add(int from,int to){    e[cont].to=to;    e[cont].next=head[from];    head[from]=cont++;}void Tarjan(int u){    vis[u]=1;    dfn[u]=low[u]=cnt++;    stack[++tt]=u;    for(int i=head[u];i!=-1;i=e[i].next)    {        int v=e[i].to;        if(vis[v]==0)Tarjan(v);        if(vis[v]==1)low[u]=min(low[u],low[v]);    }    if(dfn[u]==low[u])    {        sig++;        do        {            color[stack[tt]]=sig;            vis[stack[tt]]=-1;        }        while(stack[tt--]!=u);    }}int Slove(int n){    cnt=1,sig=0,tt=-1;    memset(stack,0,sizeof(stack));    memset(color,0,sizeof(color));    memset(dfn,0,sizeof(dfn));    memset(low,0,sizeof(low));    memset(vis,0,sizeof(vis));    for(int i=1;i<=n*2;i++)    {        if(vis[i]==0)Tarjan(i);    }    for(int i=1;i<=n;i++)    {        if(color[i]==color[i+n])return 0;    }    return 1;}int main(){    int n,m;    while(~scanf("%d%d",&n,&m))    {        cont=0;        memset(head,-1,sizeof(head));        for(int i=1;i<=100040;i++)s[i].clear();        for(int i=1;i<=n;i++)scanf("%d",&a[i]);        for(int i=1;i<=m;i++)        {            int k;            scanf("%d",&k);            while(k--)            {                int num;                scanf("%d",&num);                s[num].push_back(i);            }        }        for(int i=1;i<=n;i++)        {            int u=s[i][0];            int v=s[i][1];            if(a[i]==0)            {                add(u,v+m);                add(v+m,u);                add(v,u+m);                add(u+m,v);            }            if(a[i]==1)            {                add(u,v);                add(v,u);                add(u+m,v+m);                add(v+m,u+m);            }        }        int ans=Slove(m);        if(ans==1)printf("YES\n");        else printf("NO\n");    }}





0 0
原创粉丝点击