您的位置:首页 > 其它

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

2017-02-24 12:43 453 查看
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 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 and m (2 ≤ n ≤ 105, 2 ≤ 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 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个开关,对于这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");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Codeforces#400
相关文章推荐