紧密连接的组件


16

如果图形中存在彼此之间的路径,则有向图中的两个不同的顶点将牢固连接。图的强连接组件是图的子集,以使子集中的每对不同的顶点都牢固连接,向子集中添加更多的顶点会破坏此属性。

您面临的挑战是将图分离为其紧密连接的组件。具体来说,您必须输出图中的所有SCC。

输入/输出:

作为输入,您可以使用有向边列表,邻接列表,邻接矩阵或任何其他合理的输入格式。询问您是否不确定。您可以假设图形没有完全断开的顶点,并且不存在自身边,但是您可以不做任何进一步的假设。您也可以选择将顶点列表以及顶点数量作为输入。

作为输出,您必须给出顶点的分区,例如顶点列表的列表(其中每个子列表是一个紧密连接的组件),或者给出顶点的标签(其中每个标签对应于一个不同的组件)。

如果使用标签,则标签必须是顶点或连续的整数序列。这是为了防止将计算拖到标签中。

例子:

这些示例获取边的列表,其中每个边从第一个条目指向第二个条目,并输出分区。您可以自由使用此格式或其他格式。

输入在第一行,输出在第二行。

[[1, 2], [2, 3], [3, 1], [1, 4]]
[[1, 2, 3], [4]]

[[1, 2], [2, 3], [3, 4]]
[[1], [2], [3], [4]]

[[1, 2], [2, 1], [1, 3], [2, 4], [4, 2], [4, 3]]
[[1, 2, 4], [3]]

[[1, 2], [2, 3], [2, 5], [2, 6], [3, 4], [3, 7], [4, 3], [4, 8], [5, 1], [5, 6], [6, 7], [7, 6], [8, 7], [8, 4]]
[[1, 2, 5], [3, 4, 8], [6, 7]]

评分和限制:

一如既往,禁止出现标准漏洞。此外,禁止专门处理强连接组件的内置程序。

根据提供的示例,解决方案应在不超过一个小时的时间内运行。(这是为了防止缓慢的指数解,仅此而已。)

这是代码高尔夫。最少的字节数获胜。


我们为连接的组件分配的标签的灵活性如何?例如,该组件中的顶点索引列表是否为有效标签?
xnor

@xnor完全灵活。应该通过相等测试/相同的字符串进行匹配。
isaacg '16

我们的图形输入格式是否还可以包含顶点数量和/或顶点标签列表?
xnor

@xnor两者都可以。我将对其进行编辑
。– isaacg

在最后一个测试用例中,我得到的8是该组件中没有,[3,4]因为它不能6同时7(每个都不能到达)。
xnor

Answers:


7

Python 2使用numpy,71 62字节

import numpy
def g(M,n):R=(M+M**0)**n>0;print(R&R.T).argmax(0)

将输入作为numpy代表邻接关系和节点数的矩阵。产生输出作为numpy行矩阵,该输出矩阵通过其组件中的最低顶点编号来标记每个顶点。

对于邻接矩阵M,矩阵幂M**n计算n从每个起始顶点到每个结束顶点的-step路径数。将身份添加到MviaM+M**0会修改邻接矩阵,以向每个边缘添加一个自环。因此,(M+M**0)**n最多统计长度的路径n(有冗余)。

由于任何路径最多具有长度n,因此可以从其到达(i,j)顶点的任何节点数对应于的正项。然后,可达性矩阵为,从此开始工作。ji(M+M**0)**nR=(M+M**0)**n>0>0

计算入口方式andR&R.TR.T转置在哪里,然后给出一个矩阵,该矩阵指示成对的相互可达的顶点。它的第一i行是与它在同一强连接组件中的顶点的指示符向量。取argmax每行的索引给出其中第一行的索引True,这是其组件中最小顶点的索引。


4

JavaScript(ES6),125个字节

a=>a.map(([m,n])=>(e[m]|=1<<n|e[n],e.map((o,i)=>o&1<<m?e[i]|=e[m]:0)),e=[])&&e.map((m,i)=>e.findIndex((n,j)=>n&1<<i&&m&1<<j))

将有向对的列表作为参数,而结果是每个顶点的数组,使第一个顶点牢固地与其相连,我认为这是有效的标记。例如,使用输入[[1, 2], [2, 3], [2, 5], [2, 6], [3, 4], [3, 7], [4, 3], [4, 8], [5, 1], [5, 6], [6, 7], [7, 6], [8, 7], [8, 4]]返回[, 1, 1, 3, 3, 1, 6, 6, 3](没有顶点0;顶点1、2和5具有标签1; 3、4和8具有标签3,而6和7具有标签6)。


4

MATL26 22字节

tnX^Xy+HMY^gt!*Xu!"@f!

这使用与@xnor答案相同的方法

当前版本(15.0.0)中工作该语言的中工作。

输入是图的邻接矩阵,行之间用分号分隔。第一个和最后一个测试用例是

[0 1 0 1; 0 0 1 0; 1 0 0 0; 0 0 0 0]

[0 1 0 0 0 0 0 0; 0 0 1 0 1 1 0 0; 0 0 0 1 0 0 1 0; 0 0 1 0 0 0 0 1; 1 0 0 0 0 1 0 0; 0 0 0 0 0 0 1 0; 0 0 0 0 0 1 0 0; 0 0 0 1 0 0 1 0]

在线尝试!

t     % implicitly input adjacency matrix. Duplicate
n     % number of elements
X^    % square root
Xy    % identity matrix of that size
+     % add to adjacency matrix
HM    % push size again
Y^    % matrix power
g     % convert to logical values (0 and 1)
t!*   % multiply element-wise by transpose matrix
Xu    % unique rows. Each row is a connected component
!     % transpose
"     % for each column
  @   %   push that column
  f!  %   indices of nonzero elements, as a row
      % end for each. Implicitly display stack contents

3

Pyth,13个字节

.gu+Gs@LQG.{k

演示测试套件

输入是一个邻接表,表示为一个字典,该字典将顶点映射到它具有边的顶点列表(其有向邻居)。输出是一个分区。

该程序的本质是找到每个顶点可到达的顶点集,然后按这些顶点将顶点分组。同一SCC中的任何两个顶点都可以从它们到达同一组顶点,因为每个顶点可以彼此到达,并且可达性是可传递的。不同组件中的任何顶点都具有不同的可达集,因为这两个顶点集都不包含另一个顶点集。

代码说明:

.gu+Gs@LQG.{k
                  Implicit: Q is the input adjacency list.
.g           Q    Group the vertices of Q by (Q is implicit at EOF)
  u       .{k     The fixed point of the following function, 
                  starting at the set containing just that vertex
   +G             Add to the set
     s            The concatenation of
      @LQG        Map each prior vertex to its directed neighbors
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.