并查集+思维——The Door Problem
一、问题描述(题目链接)
有n个门和m个开关,每个开关可以控制任意多的门,每个门严格的只有两个开关控制,问能否通过操作某些开关使得所有门都打开。(给出门的初始状态)。
二、问题分析
大部分开关问题首先要想到的一点就是任何开关操作两次以上都是无意义的,因此对于每个开关,我们要么操作一次,要么不操作。
因为已知门的初始状态,每个门由两个开关控制,所以我们可以调节这两个开关,使门保持打开的状态。
我们考虑用并查集维护开关之间的关系,因为每个开关有操作和不操作两种状态。,因此,我们要把每个点拆成两个点,i表示第i个开关没操作过,i+m表示第i个开关操作过。
若第i个门初始状态为1,控制开关为a和b,则合并a,b和a+m,b+m。
若初始状态为0,则合并a,b+m和b,a+m
最后判断i 和i+ m是否在同一集合,有任意一个,则不存在使门全部呈打开状态的操作。
三、代码实现
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
using namespace std; const int maxn = + ;
const int maxm = + ;
int n, m, sta[maxn];
int fa[ * maxn];
vector<int>door[maxn]; void init()
{
for (int i = ; i <= * maxm; i++)
fa[i] = i;
} int findset(int x)
{
if (x != fa[x])
return fa[x] = findset(fa[x]);
return fa[x];
} void unite(int x, int y)
{
int rx = findset(x);
int ry = findset(y);
fa[rx] = ry;
} int main()
{
int flag = ;
init();
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++)
scanf("%d", &sta[i]);
for (int i = ; i <= m; i++)
{
int cnt,tmp;
scanf("%d", &cnt);
while (cnt--)
{
scanf("%d", &tmp);
door[tmp].push_back(i); //输入的是每个开关控制的门,我们要建立的是每个门由哪些开关控制
}
} for (int i = ; i <= n; i++)
{
if (sta[i])
{
unite(door[i][], door[i][]);
unite(door[i][] + m, door[i][] + m);
}
else
{
unite(door[i][] + m, door[i][]);
unite(door[i][], door[i][] + m);
}
}
for (int i = ; i <= m; i++)
{
if (findset(i) == findset(i + m))
{
flag = ;
break;
}
}
printf("%s\n", flag ? "YES" : "NO");
return ;
}
并查集+思维——The Door Problem的更多相关文章
- F - Number of Connected Components UVALive - 7638 (并查集 + 思维)
题目链接:https://cn.vjudge.net/contest/275589#problem/F 题目大意:就是给你n个数,如果说两个数之间的gcd!=1,那么就将这两个点连起来,问你最终这些点 ...
- [codeforces 859 E] Desk Disorder 解题报告 (并查集+思维)
题目链接:http://codeforces.com/problemset/problem/859/E 题目大意: 有$n$个人,$2n$个座位. 给出这$n$个人初始的座位,和他们想坐的座位. 每个 ...
- CodeForces - 763A(并查集/思维)
题意 https://vjudge.net/problem/CodeForces-763A 一棵无根树中各个节点被染上了一种颜色c[i] 现在让你选择一个点作为根节点,使得这个根节点的所有儿子满足以该 ...
- 并查集+思维——X-Plosives
一.问题描述(题目链接) 有n种化合物,每种化合物由两种元素组成.当几种的化合物数量等于他们所含不同元素的数量时,就会发生爆炸.现在依次给出化合物的组成,当新的化合物与之前的化合物放在一起会发生爆炸时 ...
- 79: cf 444E 并查集+思维
$des$ 题面 $sol$ 把边从小到大排序,枚举每条边作为答案,然后把两个点合并,判断每条边是否可以作为答案时,$cnt_i$ 表示节点 $i$ 已经合并的 $x$ 之和$size_i$ 表示已经 ...
- Codeforces Round #600 (Div. 2) D题【并查集+思维】
题意:给你n个点,m条边,然后让你使得这个这个图成为一个协和图,需要加几条边.协和图就是,如果两个点之间有一条边,那么左端点与这之间任意一个点之间都要有条边. 思路:通过并查集不断维护连通量的最大编号 ...
- 洛谷 P2391.白雪皑皑 (并查集,思维)
题意:有\(n\)个点,对这些点进行\(m\)次染色,第\(i\)次染色会把区间\((i*p+q)\ mod\ N+1\)和\((i*q+p)\ mod\ N+1\)之间的点染成颜色\(i\),问最后 ...
- B - Rikka with Graph HDU - 5631 (并查集+思维)
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some mat ...
- Codeforces 722C(并查集 + 思维)
本文链接:http://www.cnblogs.com/Ash-ly/p/5932712.html 题目链接:http://codeforces.com/problemset/problem/722/ ...
随机推荐
- 20个Flutter实例视频教程-第12节: 流式布局 模拟添加照片效果
视频地址: https://www.bilibili.com/video/av39709290/?p=12 博客地址: https://jspang.com/post/flutterDemo.html ...
- FTP服务基础
网络文件共享 本章内容 FTP服务 NFS服务 SAMBA服务 DAS.NAS.SAN(文件) DAS:开放系统的直连式存储(Direct-Attached Storage) 磁盘连接到本机的电脑上, ...
- 梦工厂实验室 取石子之fans 博弈
问题 D: 取石子之fans 时间限制: 1 Sec 内存限制: 64 MB提交: 57 解决: 26[提交][状态][讨论版] 题目描述 Yougth和Hrdv玩一个游戏,拿出n个石子摆成一圈, ...
- CSS3 制作魔方 - 相关立体样式
最好的实践,就是给定一个实践的目标去实践. 目标:利用 CSS3 的一些特性,绘制一个魔方,要可以玩转的那种,即上下左右每一层都可以独立旋转.效果如下: 为了完成此效果,将使用到以下相关概念和样式:坐 ...
- Maven 依赖范围(转)
1.什么是依赖范围? maven 项目不同的阶段引入到classpath中的依赖是不同的,例如,编译时,maven 会将与编译相关的依赖引入classpath中,测试时,maven会将测试相关的的依赖 ...
- Lightoj 1082【RMQ】
这里很low地写了个线段树... #include <bits/stdc++.h> using namespace std; typedef long long LL; const int ...
- C++函数调用过程深入分析
http://blog.csdn.net/dongtingzhizi/article/details/6680050 0. 引言 函数调用的过程实际上也就是一个中断的过程,那么C++中到底是怎样实现一 ...
- 洛谷P3960 列队(Splay)
传送门 感觉自己好久不打数据结构已经完全不会了orz…… 据说正解树状数组?然而并不会 首先考虑一下每一次操作,就是把一个人从这一行中取出并放到行的最后,再从最后一列取出放到列的最后 那么这两种操作其 ...
- IT兄弟连 JavaWeb教程 JSP内置对象3
读取web.xml配置信息的config对象 config对象主要用于取得服务器的配置信息.通过pageContxt对象的getServletConfig()方法获取一个config对象.当一个Ser ...
- PostgreSQL - 用psql 运行SQL文件
对于预先写好的SQL文件,比如/home/user1/updateMyData.sql, 可以有两种方式来运行这个SQL文件. 方式一:连接db后执行SQL文件 首先通过psql连接到对应的db: p ...