我有一个有向图的 n x n 邻接矩阵。我想搜索以查看是否有任何列总结为 n 。问题是我必须在 O(n)时间内完成此操作。有没有办法用 O(n)时间来处理这个问题,或者它是不可能的(不需要代码)?
供参考,以下是我要解决的问题:
在学校的乐队选举期间,每个人对总统都有一些偏好,而且一个人的偏好一直包括他/她自己。 “完美”的总统是每个人的偏好,除了他/她自己不喜欢任何人。我们想要知道的是这样的人是否存在。
- 定义一个有向图,其中候选集作为顶点,并且从顶点 a 到顶点 b 的有向边,当且仅当 b 在 a 的首选项集中。
- n 人
- 我们想要一个在 O(n)时间
中执行的算法- 我们以 n x n 邻接矩阵的形式给出了上述图形
我认为如果每个人都投票选出“完美的总统”,那么他/她将拥有 n 传入节点,因此对该列进行求和应该给我们 n 。如果有更好的方法来解决这个问题而不是我正在做的事情,那么任何提示都会受到赞赏,以指导我朝着正确的方向前进。
答案 0 :(得分:5)
让我重复规则并给出数字以便于参考:
让我们定义邻接矩阵,以便当人 i 有一个时,行 i 和列 j 中的值为1对人 j 的偏好。所有其他值均为0.
上述三条规则可以根据邻接矩阵重新制定如下:
请注意,不能有两个或更多完美的总统,因为他们必须彼此偏好(规则2),这违反了规则3.
完美的总统(如果存在)可以在线性时间内找到,通过从邻接矩阵的左上角(第0行,第0列)进行锯齿形,根据以下规则:
观察:由于规则1,算法的这一部分永远不会进入主对角线上面的值:该对角线上的1值就像一个每当我们碰到它时,墙壁就会向我们推进。因此,您将始终通过从最后一行向下移动来退出矩阵。在最极端的情况下,它将是在矩阵的右下角(在对角线上)的1向下移动。
这是一个邻接矩阵的简单示例,其中箭头表示算法如何指示从左上角到底行某处的1的路径:
1 1 0 1 0
↓
1 1 0 1 0
↓
0 → 1 1 1 0
↓
0 0 → 0 → 1 0
↓
0 1 1 1 1
↓
=p
请注意,在这个例子中有一个完美的总统,但这当然不是一个要求:算法会给你一个值 p ,无论是否有一个完美的总统。
声明:完美的总统,如果有的话,必须是号码 p 的人。
给定的是上述Zig-zag算法返回的 p 。
首先,我们通过矛盾来证明:
所以让我们假设相反:完美的总统是人我和 i< P :
由于我们在第0列中开始了zig-zag阶段并最终在 p 列中,并且由于我们在此过程中无法跳过列,因此有一段时间我们在列 I 的。由于我们没有停留在该列中,因此它必须意味着列 i 在其中一行中有一个零,这会调用我们向右移动。但是规则2要求如果 i 是一个完美的总统,列 i 应该只有1个值(规则2)。矛盾!
其次,我们通过矛盾证明:
所以让我们假设相反:完美的总统是人我和 i> P :
因为我们在第0行开始Zig-zag阶段并到达最后一行(参见观察),并且由于我们在此过程中无法跳过一行,所以有一刻我们在行 i 。由于我们并没有停留在那一行,而是在某个时刻向下移动(参见观察:我们向下移动了矩阵),它必须意味着行 i 它的一列中的一个叫我们向下移动。这1不能是对角线上的1(在 [i,i] ),因为我们没有到达 i 列: i 大于 p ,算法以 p 列结束。所以它必须是行 i 中的另一个,第二个。
但是规则3要求如果 i 是一个完美的总统,那么行 i 应该只有一个1值,所有其他值都是零。矛盾!
这两个矛盾的证据让我们没有其他可能的数字,如果有一个完美的总统,而不是数字 p 。
要实际检查人 p 是否确实是一个完美的总统是微不足道的:我们可以检查列 p 是否包含所有1&#39; s和< em> p 只包含0&#39; s, i 列除外。
所有这一切都可以在线性时间内完成:至少 2n-1 在Z字形阶段需要从矩阵读取,而 2n-2 更多最后的验证阶段。因此,这是 O(n)。