📜  门|门 CS 1999 |第 69 题(1)

📅  最后修改于: 2023-12-03 15:42:21.112000             🧑  作者: Mango

门|门 CS 1999 |第 69 题

题目描述

有 $n$ 个开关和 $m$ 个门,每个门需要若干个开关的状态满足一定条件才能打开。其中,每个开关最多只能影响一个门的状态,每个门需要的开关数量不少于 $k$ 个( $k$ 是给定参数)。现在给出每个门需要哪些开关的状态才能打开,以及每个开关能影响哪些门的状态,问有没有一种方案,使得所有的门都能打开,如果有输出 "YES",否则输出 "NO"。

输入格式

输入的第一行包含 3 个整数 $n$、$m$、$k$,分别表示开关数量、门数量、每个门需要的开关数量不少于 $k$ 个。

接下来的 $m$ 行,每行开头的一个整数 $t$,表示这个门需要开关的数量 $t$,后面 $t$ 个整数 $x_{1},x_{2},...,x_{t}$,表示这个门需要的开关编号(1 到 $n$ 之间的整数)

接下来的 $n$ 行,第 $i$ 行开头的整数 $t$,表示第 $i$ 个开关能影响的门数量,接下来 $t$ 个整数 $y_{i,1},y_{i,2},...,y_{i,t}$,表示这个开关能影响的门编号。

输出格式

如果存在一种方案,使得所有门都能打开,输出 "YES",否则输出 "NO"。

数据范围

$1 \leq n, m \leq 1000$,$1 \leq k \leq n$,$1 \leq t \leq n, t \leq 30$。

输入样例
3 3 2
2 1 2
2 2 3
2 1 3
2 1 2
2 1 3
2 2 3
输出样例
YES
题目分析

对于这道题,我们可以使用最小割来解决。

先将所有开关看做一个点,所有门看做另一个点,然后,每个开关 $i\in [1, n]$ 到门 $j\in [1, m]$ 之间连一条边,边权为 $w_{ij}=1$。表示第 $i$ 个开关能否影响第 $j$ 个门的状态。也就是说,如果第 $i$ 个开关和第 $j$ 个门之间有一条边,则表示开关 $i$ 能够影响门 $j$ 的状态。

接着,下面的操作就跟最小割的一般操作一样了。

题目给定了每个门至少需要 $k$ 个开关,那么我们可以从源点 $S$ 向每个开关 $i$ 连一条容量为 $1$ 的边,然后从每个门 $j$ 向汇点 $T$ 连一条容量为 $k$ 的边。

然后,对于每次都可以增加整张图的最小割值。具体的做法是在残量网络上,从源点开始通过广度优先搜索寻找任意一条从源点到汇点的增广路,并将增广路上的边的容量都减去最小可行流量。这样的操作,可以在 $O(m\cdot E)$ 的时间内完成。其中,$m$ 表示边的数量,$E$ 表示最大单次残量网络中边的数量。

最后,判断经过最小割后,能否从源点 $S$ 到达汇点 $T$。如果能,则表示所有的门都能打开,否则,表示有门是无法被打开的。时间复杂度是 $O(m^2 \cdot E)$,即 $O(n^5)$ 级别。

参考代码