CF1765A Access Levels 题解
根据题意,发现要把矩阵一列一列的分组,所以我们从列出发,而不是行。
首先考虑两列如何才能在一组。假设两列存在包含关系,就可以在一组。证明为:
-
假设两列不存在包含关系,那么一定存在两行,第一列这行是 \(0\),第二列是 \(1\),另一行呢,便是第一列是 \(1\),第二列是 \(0\)。容易发现如果单单考虑这两行便不能在一起,那么两列就一定不能包含在一起。由于这样的两行是对称的,所以两列的权限要求一定是相等的,而这时候用户无论有什么样的访问权限,都不能满足要求。
-
假设这一组每两列都存在包含关系,那么我们可以直接构造出方案,不用特意证明。
构造:
-
单独考虑每一组。把这一组的每一列都赋一个权值,等于这一列的 \(1\) 的个数,由于 \(1\) 越多,这一列就需要被越多用户访问到,所以他的权限要求就越小,那么把这些列排序后,从大到小依次把权限要求设置为 \(2,3,4,\cdots,k\)(从 \(2\) 开始是为了给下面的构造留值) 即可。
-
我们把这些列排序完就会发现,每一行都是 \(111 \cdots 000\),因为这些列存在包含关系。那么我们这一行的用户,直接枚举这一行有多少个 \(1\),记为 \(x\),则他的访问权限就是 \(x + 1\),意味着他可以访问前 \(x\) 个文件,\(+ 1\) 是因为权限必须是正整数。
现在只要找到最小分组并构造出来即可。上图。\(n \le 500\),所以可以直接暴力寻找哪些列包含哪些列,设 \(i\) 包含 \(j\),则连边 \(i\) -> \(j\),因为如果 \(i\) 包含 \(j\),\(j\) 包含 \(k\),则 \(i\) 一定包含 \(k\),所以我们只需要找到几条链覆盖所有点即可。发现这是最小路径覆盖,可以二分图,我写了网络流,构造出来方案就行了。
我的网络流笔记 里面网络流板子讲的比较简略,但是最小路径覆盖可以参考参考。
代码比较丑,因为写了不少假做法。

浙公网安备 33010602011771号