📜  门|门 IT 2005 |第 89 题

📅  最后修改于: 2021-09-24 05:13:33             🧑  作者: Mango

Q84 Part_B
有向图中的汇是一个顶点 i,使得每个顶点 j ≠ i 到 i 都有一条边,并且没有从 i 到任何其他顶点的边。具有 n 个顶点的有向图 G 由其邻接矩阵 A 表示,其中 A[i] [j] = 1 如果存在从顶点 i 指向 j 的边,否则为 0。以下算法确定图 G 中是否存在汇点。
i = 0
do {
    j = i + 1;
    while ((j < n) && E1) j++;
    if (j < n) E2;
} while (j < n);

flag = 1;
for (j = 0; j < n; j++)
    if ((j! = i) && E3)
        flag = 0;

if (flag)
    printf("Sink exists");
else
    printf("Sink does not exist");

为 E3 选择正确的表达式

(A) (A[i][j] && !A[j][i])
(B) (!A[i][j] && A[j][i])
(C) (!A[i][j] | | A[j][i])
(D) (A[i][j] | | !A[j][i])

答案: (D)
说明:以下说明针对此问题的上一部分:
对于要成为汇的顶点 i,从 i 到任何其他顶点不应该有边。

下沉

根据有问题的输入,

A[i][j] = 1 means there is an edge from vertex i to j.
A[i][j] = 0 means there is no edge from i to j

要使 i 的节点下沉,

A[i][j] should be 0 for all j 
A[j][i] should be 1 for all j.

上面的伪代码从 i = 0 开始检查每个顶点 i 是否为接收器。它基本上检查 i 之后的每个顶点 j 是否为接收器。伪代码中的技巧是,它不检查小于 i 的 j。这个循环选择的 i 可能不会下沉。它基本上确保我们不会忽略潜在的接收器。在 do while 循环之后检查 i 是否实际上是接收器。

顶点 i 是潜在汇,而 A[i][j] 为零
因此, E1 : !A[i][j]

如果上述条件为假,则 i 不是汇。所有 j < i 也不能是汇,因为从 i 到 j 没有边。
现在,下一个潜在的汇可以是 j。
所以, E2 : i = j

这个问题的解释
以下伪代码主要检查上面代码选择的潜在接收器是否实际上是接收器。

flag = 1;
for (j = 0; j < n; j++)
    if ((j! = i) && E3)
        flag = 0;

flag 等于 0 表示 i 不是接收器。一旦发现 i 不是接收器,代码就会设置标志 0。

A node i is not a sink if either of the following 
two conditions become true for any j not equal to i.
A[i][j] is 1 for any j 
OR
A[j][i] is 0 for any j

E3 : (A[i][j] | | !A[j][i])

所以选项D是正确的这个问题的测验