题目描述
放假了,小明和同学们来到了游乐园,开始了他们美好的假期。
可爱的小明在平时总喜欢吹嘘自己,总说自己才是人群中最靓的仔,是全班同学的指挥中心。同学们不满小明的傲娇,于是在他们买过门票后,来到解谜屋,想为难一下小明。
进入解密屋后,他们来到第一个关卡。这是一个狭窄的房间,紧锁的门上有n个灯泡(编号从1开始),有些灯是亮着的,有些灯是熄灭的。墙上有m个开关,这些开关控制着灯泡的亮暗,每个开关会控制若干灯泡,当你按下开关时,对应的灯泡如果是亮的,就会熄灭,如果是灭的,就会亮起。且每个灯泡一定会被两个开关控制。游客可以操作这些开关,尝试是否可以点亮所有灯泡。
只有点亮所有的灯泡才能打开门进入下一关。你能帮助一脸懵逼的小明,告诉他能否通关吗?
输入格式
第一行,一个正整数T,为数据的组数。
每组数据的第一行,有两个正整数 n 和 m , n 是灯泡的数量,m 是开关的数量。
每组数据的第二行 n 个0到1之间的数,分别表示每个灯泡的状态,0 表示灯泡是灭的,1 表示灯泡是亮的。
再接下来 m 行,每行第一个数 x 表示第 i 个开关控制的灯泡数,再接着有 x 个不重复的数字ai,分别表示所控制的灯泡编号 。
输出格式
每组数据输出一行,为:“YES"或者"NO"
YES表示存在一种方案能点亮所有的灯泡,NO为不能。
注意大小写,不带引号
样例输入
1
3 4
1 0 0
2 1 2
1 2
2 1 3
1 3
样例输出
YES
提示
先按第一个开关,此时第一盏灯会熄灭,第二盏灯会亮起。
再按第三个开关,三盏灯都会亮起。
1 <= T <= 5
1 <= x,ai <= n
对于10%的数据,1 <= m,n <= 10
对于30%的数据,1 <= m,n <= 1,000
对于50%的数据,1 <= m,n <= 10,000
对于100%的数据,1 <= m,n <= 100,000
#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <vector>
#include <map>
using namespace std;
typedef long long ll;
int e[2102105];
int w[2102105][2];
int b[2102105];
int n,m,s,r,k,t,num,now,p;
const double pi=acos(-1.0);
int find (int x1)//冰茶寄一下啦
{
if(e[x1] == x1)
{
return x1;
}
return e[x1] = find(e[x1]);
}
void check (int x,int y)//冰茶寄一下啦
{
x = find(x);
y = find(y);
if(x != y)
{
e[x] = y;
}
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int t;
cin >> t;
while (t --)
{
cin >> n >> m;
for( int i = 1; i <= 2 * m; i ++)
{
e[i] = i;
}
for( int i = 1 ; i <= n; i ++)
{
w[i][0]=0,w[i][1]=0;//每个 灯泡对应俩开关所以第二位就开俩 //初始化t组数据
cin >> b[i];
}
for( int i = 1; i <= m; i ++)
{
int temp;
cin >> temp;
for( int j = 1; j <= temp; j ++)
{
int x;
cin >> x;
if(w[x][0] == 0)//挨个存入开关的初始状态和位置
{//如果是第一个控制该灯泡的开关
w[x][0] = i;
}
else//第二个
{
w[x][1] = i;
}
}
}
bool flag = true;
for ( int i = 1;i <= n; i ++)//遍历每个灯泡找出不合逻辑的
{
if(b[i] == 1)//当其点亮的
{
if(find(w[i][0]) == find(w[i][1] + m))//如果其处于不亮的逻辑下
{
flag = false;
break;
}
else//否则就进行并查集,进行合并,表示符合亮的逻辑
{
check(w[i][0] , w[i][1]);
check(w[i][0] + m , w[i][1] + m);
}
}
else//不亮
{
if(find(w[i][0]) == find(w[i][1]))//同理
{
flag = false;
break;
}
else
{
check(w[i][0] , w[i][1] + m);
check(w[i][0] + m , w[i][1]);
}
}
}
if(flag)
{
cout << "YES" << endl;
}
else
{
cout << "NO" << endl;
}
}
return 0;
}