并查集+思维——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/ ...
随机推荐
- 二Java的常量与变量-1-1标识符
类的名字就是标识符 起类名也是不能带空格的
- sql server 2008 删除某数据库所有表
/* ------sqlserver 2008 删除某数据库所有表-------- */ declare @tname varchar(8000) set @tname='' select @tnam ...
- iOS 中 延迟操作四种方式
本文列举了四种延时执行某函数的方法及其一些区别.假如延时1秒时间执行下面的方法. - (void)delayMethod { NSLog(@"execute"); } 1.perf ...
- Ogre 学习记录
http://www.cppblog.com/richardhe/articles/55722.html 1: 设计初衷 它设计初衷是完全跨平台的.抽象的接口隐藏了平台相关的细节. 它设计初衷是大幅度 ...
- CentOS 6.5 升级gcc到4.8 以及libstdc++
CentOS 6.5 自带gcc太旧不支持c11, 升级到4.8的步骤: 引用: http://cache.baiducontent.com/c?m=9d78d513d99216f31eb0d5690 ...
- [Xcode 实际操作]一、博主领进门-(5)检测运行中的模拟器在各个方向上的切换
目录:[Swift]Xcode实际操作 本文将演示Xcode的设备模拟器在各个方向上的切换和检测. 在项目导航区,打开视图控制器的代码文件[ViewController.swift] 检测运行中的模拟 ...
- Java之多线程同步基础
java学习的道路上呢总有一些麻烦的东西需要花费一些时间去理解,比如个人认为不好搞的多线程. 线程是并列运行的 因为是并列运行,所以有时候会发生资源抢占,从而导致参数变化; 比如酱紫 package ...
- 如何找出nginx配置文件的所在位置?
对于一台陌生的服务器或安装太久忘了位置,怎么才能简单快速的找到配置文件的位置呢?要找出配置文件的位置,需要先找出nginx可执行文件的路径 , 这里有几种方法: 1.如果程序在运行中 ps -ef | ...
- bzoj2825:[AHOI2012]收集资源
传送门 看到数据范围这么小,就没想过暴力的办法么 考虑肯定是从近走到远,所以走的点之间一定没有其他的点,所以我们就可以暴力的建图,然后暴力的去dfs就好了 代码: #include<cstdio ...
- [題解](單調隊列dp)【2016noip福建夏令營】探險
P1917 -- 探险 时间限制:1000MS 内存限制:131072KB 题目描述(explore.cpp) π+e去遗迹探险,遗迹里有 N 个宝箱,有的装满了珠宝,有的装着废品. π+e ...