题意:

有n个房间和m扇门,每扇门有且仅有一把钥匙
有k个人度过了两天,在第一天开始的时候所有的门都是关闭的,在第二天结束的时候,所有的门也都是关闭的
在这两天内,每个人可以执行如下操作若干次:
关上一扇门(前提:他有这扇门的钥匙,且这扇门与当前房间相连)
打开一扇门(前提:他有这扇门的钥匙,且这扇门与当前房间相连)
将自己手上的一些钥匙给与他同处于一间房里的其他人
走向一个与当前房间相连、且门是打开的房间
给出第一天开始前和第二天结束后每个人的位置及拥有的钥匙
判断是否可行

题解:

直接想不太好做。

转化一下:

可以发现,如果有解,一定可以把能打开的门都打开,在关回去。

而开和关是互逆的,所以,可以理解为两天都把能打开的门都打开。

如果都打开后,两天结果一样,则有解。

一样就是指打开的门相同,每个房间,人,钥匙所属集合分别相同。

这样就好做了。

暴力枚举能打开的边,用并查集维护每个集合的钥匙,暴力合并。

可以发现,枚举\(m\)次就够了。每次暴力合并复杂度为\(O(m)\),总时间复杂度为\(O(m^2)\)。

代码:

#include <stdio.h>
#include <map>
using namespace std;
#define ull unsigned long long
#define se 13131
int u[1005],v[1005],fa[1005],n,m,k;
bool zt[1005][1005];
int getv(int x) {
if (x == fa[x]) return x;
fa[x] = getv(fa[x]);
return fa[x];
}
void merge(int x, int y) {
x = getv(x);
y = getv(y);
if (x == y) return;
if (x < y) {
int t = x;
x = y;
y = t;
}
fa[x] = y;
for (int i = 1; i <= m; i++) {
if (zt[x][i]) zt[y][i] = true;
}
}
ull ha(char zf[1005]) {
ull rt = 0;
for (int i = 0; zf[i] != 0; i++) rt = rt * se + zf[i];
return rt;
}
map < ull,int > mp;
char zf[1005];
int wz[1005],rw[1005],yw[1005];
int w2[1005],r2[1005],y2[1005];
bool b1[1005],b2[1005];
int main() {
scanf("%d%d%d", &n, &m, &k);
for (int i = 1; i <= n; i++) fa[i] = i;
for (int i = 1; i <= m; i++) scanf("%d%d", &u[i], &v[i]);
for (int i = 1; i <= k; i++) {
int a,s;
scanf("%s%d%d", zf, &a, &s);
rw[i] = a;
mp[ha(zf)] = i;
for (int j = 0; j < s; j++) {
int b;
scanf("%d", &b);
zt[a][b] = 1;
yw[b] = a;
}
}
for (int a = 1; a <= m; a++) {
for (int i = 1; i <= m; i++) {
if (!b1[i] && (zt[getv(u[i])][i] || zt[getv(v[i])][i])) {
merge(u[i], v[i]);
b1[i] = true;
}
}
}
for (int i = 1; i <= n; i++) wz[i] = getv(i);
for (int i = 1; i <= m; i++) yw[i] = getv(yw[i]);
for (int i = 1; i <= k; i++) rw[i] = getv(rw[i]);
for (int i = 1; i <= n; i++) {
fa[i] = i;
for (int j = 1; j <= m; j++) zt[i][j] = 0;
}
for (int i = 1; i <= k; i++) {
int a,s;
scanf("%s%d%d", zf, &a, &s);
r2[mp[ha(zf)]] = a;
for (int j = 0; j < s; j++) {
int b;
scanf("%d", &b);
zt[a][b] = 1;
y2[b] = a;
}
}
for (int a = 1; a <= m; a++) {
for (int i = 1; i <= m; i++) {
if (!b2[i] && (zt[getv(u[i])][i] || zt[getv(v[i])][i])) {
merge(u[i], v[i]);
b2[i] = true;
}
}
}
for (int i = 1; i <= n; i++) w2[i] = getv(i);
for (int i = 1; i <= m; i++) y2[i] = getv(y2[i]);
for (int i = 1; i <= k; i++) r2[i] = getv(r2[i]);
bool zd = false;
for (int i = 1; i <= n; i++) {
if (wz[i] != w2[i]) zd = true;
}
for (int i = 1; i <= n; i++) {
if (rw[i] != r2[i]) zd = true;
}
for (int i = 1; i <= n; i++) {
if (yw[i] != y2[i]) zd = true;
}
for (int i = 1; i <= m; i++) {
if (b1[i] != b2[i]) zd = true;
}
if (zd) printf("NO");
else printf("YES");
return 0;
}

CF46F Hercule Poirot Problem的更多相关文章

  1. Codeforces 图论题板刷(2000~2400)

    前言 首先先刷完这些在说 题单 25C Roads in Berland 25D Roads not only in Berland 9E Interestring graph and Apples ...

  2. 1199 Problem B: 大小关系

    求有限集传递闭包的 Floyd Warshall 算法(矩阵实现) 其实就三重循环.zzuoj 1199 题 链接 http://acm.zzu.edu.cn:8000/problem.php?id= ...

  3. No-args constructor for class X does not exist. Register an InstanceCreator with Gson for this type to fix this problem.

    Gson解析JSON字符串时出现了下面的错误: No-args constructor for class X does not exist. Register an InstanceCreator ...

  4. C - NP-Hard Problem(二分图判定-染色法)

    C - NP-Hard Problem Crawling in process... Crawling failed Time Limit:2000MS     Memory Limit:262144 ...

  5. Time Consume Problem

    I joined the NodeJS online Course three weeks ago, but now I'm late about 2 weeks. I pay the codesch ...

  6. Programming Contest Problem Types

        Programming Contest Problem Types Hal Burch conducted an analysis over spring break of 1999 and ...

  7. hdu1032 Train Problem II (卡特兰数)

    题意: 给你一个数n,表示有n辆火车,编号从1到n,入站,问你有多少种出站的可能.    (题于文末) 知识点: ps:百度百科的卡特兰数讲的不错,注意看其参考的博客. 卡特兰数(Catalan):前 ...

  8. BZOJ2301: [HAOI2011]Problem b[莫比乌斯反演 容斥原理]【学习笔记】

    2301: [HAOI2011]Problem b Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 4032  Solved: 1817[Submit] ...

  9. [LeetCode] Water and Jug Problem 水罐问题

    You are given two jugs with capacities x and y litres. There is an infinite amount of water supply a ...

随机推荐

  1. java日志框架系列(9):logback框架过滤器(filter)详解

    过滤器放在了logback-classic模块中. 1.logback-classic模块中过滤器 分类(2种):常规过滤器.TurboFilter过滤器. 1.常规过滤器 常规过滤器可以通过自定义进 ...

  2. HTTP最常见的请求头

    HTTP最常见的请求头如下: l         Accept:浏览器可接受的MIME类型: l         Accept-Charset:浏览器可接受的字符集: l         Accept ...

  3. go 通过赋值给 _ 来忽略序号和值

    go 语言中 只要想忽略的值都需要用 下划线 _ 来代替 package main import "fmt" func main() {     pow := make([]int ...

  4. 【规律】Farey Sums

    [参考博客]: https://blog.csdn.net/meopass/article/details/82952087 Farey Sums 题目描述 Given a positive inte ...

  5. (六)springmvc之ModelAndView、Model、Map、ModelMap

    <a href="<%=request.getContextPath()%>/responseData/response_1">使用原生的作用域</a ...

  6. 数据仓库之抽取数据:通过bcp命令行导入数据

    原文:数据仓库之抽取数据:通过bcp命令行导入数据 在做数据仓库时,最重要的就是ETL的开发,而在ETL开发中的第一步,就是要从原OLTP系统中抽取数据到过渡区中,再对这个过渡区中的数据进行转换,最后 ...

  7. IDEA安装及默认配置习惯配置(一)

    最新新转战IDEA,每次安装完需要做一些操作习惯的设置,在这里记录一下,下次安装可以快速上手用. 第一步,JAVA安装 JDK官方下载地址:https://www.oracle.com 下载JDK时根 ...

  8. 关于Vue中,在方法中使用(操作)子组件获取到的数据

    已知,子组件通过props获取父组件传过来的数据,而这个数据是无法在created.mounted生命周期中使用的,只能在beforeUpdated或者updated获取到: 但是如果我们要使用这个数 ...

  9. ajax简单页面

    简单的注册页面运用ajax 主页面 <head><meta http-equiv="Content-Type" content="text/html; ...

  10. 嵌套的页面——自适应高度与跨越操作DOM

    <div id="myIframeId"> <iframe ref="myIframe" name="odpIframeName&q ...