复杂网络搜索特定结构的环

有向异构网络搜索特定结构的环or路径

1 问题描述

​ 有向异构网络,即网络中的边是有方向的,且节点分为不同类型,拥有不同属性。要从一个复杂网络中搜索出所有满足某个特定结构的环,特定结构的环即环中每个节点的类型确定。

​ 设有图 G = ( V , E , L v ) G=(V,E,L_v) G=(V,E,Lv) V V V是节点(node)集合, E E E是边(edge)集合,且 E ⊂ V × V E\subset V\times V EV×V ,用 L v L_v Lv表示节点上的标签集合,且 L v = { l 1 , l 2 , . . . , l q } L_v=\{l_1,l_2,...,l_q\} Lv={l1,l2,...,lq},需求是要找出所有某种结构的环,比如 V l 1 → V l 2 → V l 3 → V l 1 V_{l_1}\rightarrow V_{l_2}\rightarrow V_{l_3}\rightarrow V_{l_1} Vl1Vl2Vl3Vl1这种形式的环。

在这里插入图片描述

​ 比如上图中,要找出所有的 V l 1 → V l 2 → V l 3 → V l 1 V_{l_1}\rightarrow V_{l_2}\rightarrow V_{l_3}\rightarrow V_{l_1} Vl1Vl2Vl3Vl1形式的环,共有两个,分别如下:

在这里插入图片描述

2 邻接矩阵与路径数

​ 下面以4种节点类型的一个图为例介绍算法,节点的标签分别为 A , B , C , D A,B,C,D A,B,C,D,要找出所有 A → B → C → A A\rightarrow B\rightarrow C \rightarrow A ABCA类型的环,图如下所示。

在这里插入图片描述

​ 图中共有4个 A → B → C → A A\rightarrow B\rightarrow C \rightarrow A ABCA类型的环,分别为:

  1. A 1 → B 1 → C 1 → A 1 A1\rightarrow B1\rightarrow C1 \rightarrow A1 A1B1C1A1
  2. A 2 → B 1 → C 2 → A 2 A2\rightarrow B1\rightarrow C2 \rightarrow A2 A2B1C2A2
  3. A 2 → B 2 → C 2 → A 2 A2\rightarrow B2\rightarrow C2 \rightarrow A2 A2B2C2A2
  4. A 2 → B 2 → C 3 → A 2 A2\rightarrow B2\rightarrow C3 \rightarrow A2 A2B2C3A2

在这里插入图片描述

​ 首先建立邻接矩阵,邻接矩阵构建规则如下:


a i j = { 1     存在 V i → V j 边 0  不存在 V i → V j 边 a_{ij}=\left\{ \begin{aligned} 1 \ \ \ \ 存在V_i\rightarrow V_j边 \\ 0 \ 不存在V_i\rightarrow V_j边 \end{aligned} \right. aij={1    存在ViVj0 不存在ViVj


​ 按 A B C D ABCD ABCD的类型顺序,上述图的邻接矩阵如下:


M = [ 0      0      1      0      0      0      0      0 0      0      1      1      0      0      0      0 0      0      0      0      1      1      0      0 0      0      0      0      0      1      1      0 1      0      0      0      0      0      0      0 0      1      0      0      0      0      0      1 0      1      0      0      0      0      0      0 0      0      0      0      1      0      0      0 ] ⇒ M A 1 A 2 B 1 B 2 C 1 C 2 C 3 D 1 A 1 0 0 1 0 0 0 0 0 A 2 0 0 1 1 0 0 0 0 B 1 0 0 0 0 1 1 0 0 B 2 0 0 0 0 0 1 1 0 C 1 1 0 0 0 0 0 0 0 C 2 0 1 0 0 0 0 0 1 C 3 0 1 0 0 0 0 0 0 D 1 0 0 0 0 1 0 0 0 M=\begin{gathered} \begin{bmatrix} 0\ \ \ \ 0\ \ \ \ 1\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\\ 0\ \ \ \ 0\ \ \ \ 1\ \ \ \ 1\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\\ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 1\ \ \ \ 1\ \ \ \ 0\ \ \ \ 0\\ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 1\ \ \ \ 1\ \ \ \ 0\\ 1\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\\ 0\ \ \ \ 1\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 1\\ 0\ \ \ \ 1\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\\ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0\ \ \ \ 1\ \ \ \ 0\ \ \ \ 0\ \ \ \ 0 \end{bmatrix} & & & \Rightarrow & & & \begin{array}{c||cc|cc|ccc|c} M & A1 & A2 & B1 & B2 & C1 & C2 & C3 & D1 \\ \hline A1 & 0 & 0 & 1 & 0 & 0 & 0 & 0 & 0\\ A2 & 0 & 0 & 1 & 1 & 0 & 0 & 0 & 0\\ \hline B1 & 0 & 0 & 0 & 0 & 1 & 1 & 0 & 0\\ B2 & 0 & 0 & 0 & 0 & 0 & 1 & 1 & 0\\ \hline C1 & 1 & 0 & 0 & 0 & 0 & 0 & 0 & 0\\ C2 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 1\\ C3 & 0 & 1 & 0 & 0 & 0 & 0 & 0 & 0\\ \hline D1 & 0 & 0 & 0 & 0 & 1 & 0 & 0 & 0 \end{array} \end{gathered} M= 0    0    1    0    0    0    0    00    0    1    1    0    0    0    00    0    0    0    1    1    0    00    0    0    0    0    1    1    01    0    0    0    0    0    0    00    1    0    0    0    0    0    10    1    0    0    0    0    0    00    0    0    0    1    0    0    0 MA1A2B1B2C1C2C3D1A100001000A200000110B111000000B201000000C100100001C200110000C300010000D100000100


​ 将矩阵按节点类型分块,可以分为16个子矩阵,由于我们要找的是 A → B → C → A A\rightarrow B\rightarrow C \rightarrow A ABCA类型的环,仅与 A → B A\rightarrow B AB B → C B\rightarrow C BC C → A C\rightarrow A CA 3个类型的边有关,因此我们仅关注这3种边构成的邻接矩阵,分别为:


M A B = M A B B 1 B 2 A 1 1 0 A 2 1 1          M B C = M B C C 1 C 2 C 3 B 1 1 1 0 B 2 0 1 1          M C A = M C A A 1 A 2 C 1 1 0 C 2 0 1 C 3 0 1 M_{AB}= \begin{array}{c|cc} M_{AB} & B_1 & B_2 \\ \hline A_1 & 1 & 0 \\ A_2 & 1 & 1 \end{array} \ \ \ \ \ \ \ \ M_{BC}= \begin{array}{c|ccc} M_{BC} & C_1 & C_2 & C_3 \\ \hline B_1 & 1 & 1 & 0 \\ B_2 & 0 & 1 & 1 \end{array} \ \ \ \ \ \ \ \ M_{CA}= \begin{array}{c|cc} M_{CA} & A_1 & A_2 \\ \hline C_1 & 1 & 0 \\ C_2 & 0 & 1 \\ C_3 & 0 & 1 \end{array} MAB=MABA1A2B111B201        MBC=MBCB1B2C110C211C301        MCA=MCAC1C2C3A1100A2011


​ 将 M A B M_{AB} MAB M B C M_{BC} MBC相乘,得到 M A B C M_{ABC} MABC


M A B C = M A B × M B C = M A B B 1 B 2 A 1 1 0 A 2 1 1 × M B C C 1 C 2 C 3 B 1 1 1 0 B 2 0 1 1 = M A B C C 1 C 2 C 3 A 1 1 1 0 A 2 1 2 1 M_{ABC}=M_{AB}\times M_{BC}= \begin{array}{c|cc} M_{AB}& B_1 & B_2 \\ \hline A_1 & 1 & 0 \\ A_2 & 1 & 1 \end{array} \times \begin{array}{c|ccc} M_{BC} & C_1 & C_2 & C_3 \\ \hline B_1 & 1 & 1 & 0 \\ B_2 & 0 & 1 & 1 \end{array} = \begin{array}{c|ccc} M_{ABC} & C_1 & C_2 & C_3 \\ \hline A_1 & 1 & 1 & 0 \\ A_2 & 1 & 2 & 1 \end{array} MABC=MAB×MBC=MABA1A2B111B201×MBCB1B2C110C211C301=MABCA1A2C111C212C301


该矩阵表达了每个 A A A类节点到每个 C C C类节点的路径数,矩阵每个数字表示路径数量,比如第二行第二列的数字2,表示节点 A 2 A_2 A2到节点 C 2 C_2 C2并且经过 B B B类节点的路径有2条。

解释一下:这个数字2由矩阵 M A B M_{AB} MAB的第2行与矩阵 M B C M_{BC} MBC的第2列相乘得到,

其中 M A B [ A 2 ] [ B 1 ] = 1 M_{AB}[A_2][B_1]=1 MAB[A2][B1]=1表示节点 A 2 A_2 A2到节点 B 1 B_1 B1有一条路径, M B C [ B 1 ] [ C 2 ] = 1 M_{BC}[B_1][C_2]=1 MBC[B1][C2]=1表示节点 B 1 B_1 B1到节点 C 2 C_2 C2有一条路径,因此 A 2 A_2 A2经过 B 1 B_1 B1到达 C 2 C_2 C2有一条路径;

M A B [ A 2 ] [ B 2 ] = 1 M_{AB}[A_2][B_2]=1 MAB[A2][B2]=1表示节点 A 2 A_2 A2到节点 B 2 B_2 B2有一条路径, M B C [ B 2 ] [ C 2 ] = 1 M_{BC}[B_2][C_2]=1 MBC[B2][C2]=1表示节点 B 2 B_2 B2到节点 C 2 C_2 C2有一条路径,因此 A 2 A_2 A2经过 B 2 B_2 B2到达 C 2 C_2 C2有一条路径;

所以 1 × 1 + 1 × 1 = 2 1\times 1 + 1\times 1 = 2 1×1+1×1=2分别表示了上述2条路径。

​ 接下来将 M A B C M_{ABC} MABC M C A M_{CA} MCA相乘,得到 M A B C A M_{ABCA} MABCA


M A B C A = M A B C × M C A = M A B C C 1 C 2 C 3 A 1 1 1 0 A 2 1 2 1 × M C A A 1 A 2 C 1 1 0 C 2 0 1 C 3 0 1 = M A B C A A 1 A 2 A 1 1 1 A 2 1 3 M_{ABCA}=M_{ABC}\times M_{CA}= \begin{array}{c|ccc} M_{ABC} & C_1 & C_2 & C_3 \\ \hline A_1 & 1 & 1 & 0 \\ A_2 & 1 & 2 & 1 \end{array} \times \begin{array}{c|cc} M_{CA} & A_1 & A_2 \\ \hline C_1 & 1 & 0 \\ C_2 & 0 & 1 \\ C_3 & 0 & 1 \end{array} = \begin{array}{c|cc} M_{ABCA} & A_1 & A_2 \\ \hline A_1 & 1 & 1 \\ A_2 & 1 & 3 \end{array} MABCA=MABC×MCA=MABCA1A2C111C212C301×MCAC1C2C3A1100A2011=MABCAA1A2A111A213


该矩阵表达了每个 A A A类节点到每个 A A A类节点的路径数,以第2行第2列的数字3为例,其表示节点 A 2 A_2 A2先经过 B B B类节点再经过 C C C类节点最终到达节点 A 2 A_2 A2路径有3条。

这个数字3由矩阵 M A B C M_{ABC} MABC的第2行与矩阵 M C A M_{CA} MCA的第2列相乘得到,

其中 M A B C [ A 2 ] [ C 1 ] = 1 M_{ABC}[A_2][C_1]=1 MABC[A2][C1]=1表示节点 A 2 A_2 A2经过 B B B类节点再到节点 C 1 C_1 C1有1条路径, M C A [ C 1 ] [ A 2 ] = 0 M_{CA}[C_1][A_2]=0 MCA[C1][A2]=0表示节点 C 1 C_1 C1到节点 A 2 A_2 A2没有直接路径,因此 A 2 A_2 A2经过 B B B类节点和 C 1 C_1 C1节点到达 A 2 A_2 A2没有路径;

M A B C [ A 2 ] [ C 2 ] = 2 M_{ABC}[A_2][C_2]=2 MABC[A2][C2]=2表示节点 A 2 A_2 A2经过 B B B类节点再到节点 C 2 C_2 C2有2条路径, M C A [ C 2 ] [ A 2 ] = 1 M_{CA}[C_2][A_2]=1 MCA[C2][A2]=1表示节点 C 2 C_2 C2到节点 A 2 A_2 A2有1条路径,因此 A 2 A_2 A2经过 B B B类节点和 C 2 C_2 C2节点到达 A 2 A_2 A2 2 × 1 = 2 2\times 1=2 2×1=2条路径;

M A B C [ A 2 ] [ C 3 ] = 1 M_{ABC}[A_2][C_3]=1 MABC[A2][C3]=1表示节点 A 2 A_2 A2经过 B B B类节点再到节点 C 3 C_3 C3有1条路径, M C A [ C 3 ] [ A 2 ] = 1 M_{CA}[C_3][A_2]=1 MCA[C3][A2]=1表示节点 C 3 C_3 C3到节点 A 2 A_2 A2有1条路径,因此 A 2 A_2 A2经过 B B B类节点和 C 3 C_3 C3节点到达 A 2 A_2 A2 1 × 1 = 1 1\times 1=1 1×1=1条路径;

所以 A 2 A_2 A2先经过 B B B类节点再经过 C C C类节点最终回到 A 2 A_2 A2的路径共有: 1 × 0 + 2 × 1 + 1 × 1 = 3 1\times 0 + 2\times 1 +1\times 1= 3 1×0+2×1+1×1=3条。

3 找出所有具体的环

​ 由第二节可以得到任意两个节点间,通过任意类型的节点的路径数,若关注环则只需要关注最终矩阵中的对角线元素,也就是自己回到自己的路径数。

​ 现在需要把每一个这种类型的环由哪些节点构成找出来,其实由上面矩阵相乘的内部分析已经可以看出每一个环了,但是如果网络节点非常多,像上面那样顺着相乘并且乘到哪都把相应的路径记录下来,可能在相乘了几个矩阵时,对应的路径会非常多,而实际上最终需要找的路径或环没有那么多,这会大量消耗计算空间和时间。

​ 举个极端例子,一个网络有4000个节点,其中 A , B , C , D A,B,C,D A,B,C,D类型的节点各1000个,其中 A → B , B → C , C → D A\rightarrow B,B\rightarrow C,C\rightarrow D AB,BC,CD均全连接,那么这三种类型的边各有1000000个, A → B → C → D A\rightarrow B\rightarrow C\rightarrow D ABCD这种类型的路径将有 1 0 18 10^{18} 1018条,然而, D → A D\rightarrow A DA的边一条都没有,因此 A → B → C → D → A A\rightarrow B\rightarrow C\rightarrow D\rightarrow A ABCDA类型的环一个都没有,于是前面计算并存储的那么多路径都没有用,在最后一步都被约束掉了。那么如果先从边数最少的那个类型开始算呢?事实上路径的中期还是会有很多可能,但路径长了以后就逐渐被约束掉了。这种方法其实相当于暴力搜索。

​ 因此我们从矩阵相乘得到的最终结果出发,逐个往前推,逐层将节点寻找出来,下面具体展开第2节的例子~


M A B C A A 1 A 2 A 1 1 1 A 2 1 3 \begin{array}{c|cc} M_{ABCA} & A_1 & A_2 \\ \hline A_1 & 1 & 1 \\ A_2 & 1 & 3 \end{array} MABCAA1A2A111A213


​ 由 M A B C A M_{ABCA} MABCA的对角线可知,共有4个 A → B → C → A A\rightarrow B\rightarrow C \rightarrow A ABCA类型的环,因此首先建立4条链表,用来存储这4个环,而且还可以知道,其中1条是 A 1 A_1 A1 A 1 A_1 A1的,3条是 A 2 A_2 A2 A 2 A_2 A2的,因此每条链表中最后一个节点分别是 A 1 A_1 A1 A 2 A_2 A2 A 2 A_2 A2 A 2 A_2 A2。并且先建立一个队列,放入对角线两个元素的位置 [ A 1 ] [ A 1 ] , [ A 2 ] [ A 2 ] [A_1][A_1],[A_2][A_2] [A1][A1],[A2][A2],后面需要用到~

在这里插入图片描述

​ 接下来往前推,为了找到连在 A A A类节点前面的 C C C类节点,需要用到 M A B C , M C A M_{ABC},M_{CA} MABC,MCA矩阵。


M A B C A = M A B C × M C A = M A B C C 1 C 2 C 3 A 1 1 1 0 A 2 1 2 1 × M C A A 1 A 2 C 1 1 0 C 2 0 1 C 3 0 1 = M A B C A A 1 A 2 A 1 1 1 A 2 1 3 M_{ABCA}=M_{ABC}\times M_{CA}= \begin{array}{c|ccc} M_{ABC} & C_1 & C_2 & C_3 \\ \hline A_1 & 1 & 1 & 0 \\ A_2 & 1 & 2 & 1 \end{array} \times \begin{array}{c|cc} M_{CA} & A_1 & A_2 \\ \hline C_1 & 1 & 0 \\ C_2 & 0 & 1 \\ C_3 & 0 & 1 \end{array} = \begin{array}{c|cc} M_{ABCA} & A_1 & A_2 \\ \hline A_1 & 1 & 1 \\ A_2 & 1 & 3 \end{array} MABCA=MABC×MCA=MABCA1A2C111C212C301×MCAC1C2C3A1100A2011=MABCAA1A2A111A213


M A B C A [ A 1 ] [ A 1 ] = 1 M_{ABCA}[A_1][A_1]=1 MABCA[A1][A1]=1是由 M A B C [ A 1 ] [ C 1 ] × M C A [ C 1 ] [ A 1 ] + M A B C [ A 1 ] [ C 2 ] × M C A [ C 2 ] [ A 1 ] + M A B C [ A 1 ] [ C 3 ] × M C A [ C 3 ] [ A 1 ] M_{ABC}[A_1][C_1]\times M_{CA}[C_1][A_1]+M_{ABC}[A_1][C_2]\times M_{CA}[C_2][A_1]+M_{ABC}[A_1][C_3]\times M_{CA}[C_3][A_1] MABC[A1][C1]×MCA[C1][A1]+MABC[A1][C2]×MCA[C2][A1]+MABC[A1][C3]×MCA[C3][A1]得到的,其中后面两项都为0,有效的只有第一项 M A B C [ A 1 ] [ C 1 ] × M C A [ C 1 ] [ A 1 ] M_{ABC}[A_1][C_1]\times M_{CA}[C_1][A_1] MABC[A1][C1]×MCA[C1][A1],也就是表示 A 1 → B → C → A 1 A_1\rightarrow B\rightarrow C \rightarrow A_1 A1BCA1由一条 A 1 → B → C 1 A_1\rightarrow B\rightarrow C_1 A1BC1路径和一条 C 1 → A 1 C_1\rightarrow A_1 C1A1路径组合而成,因此图中第一个 A 1 A_1 A1节点前面应该连 C 1 C_1 C1节点。

M A B C A [ A 2 ] [ A 2 ] = 3 M_{ABCA}[A_2][A_2]=3 MABCA[A2][A2]=3是由 M A B C [ A 2 ] [ C 1 ] × M C A [ C 1 ] [ A 2 ] + M A B C [ A 2 ] [ C 2 ] × M C A [ C 2 ] [ A 2 ] + M A B C [ A 2 ] [ C 3 ] × M C A [ C 3 ] [ A 2 ] M_{ABC}[A_2][C_1]\times M_{CA}[C_1][A_2]+M_{ABC}[A_2][C_2]\times M_{CA}[C_2][A_2]+M_{ABC}[A_2][C_3]\times M_{CA}[C_3][A_2] MABC[A2][C1]×MCA[C1][A2]+MABC[A2][C2]×MCA[C2][A2]+MABC[A2][C3]×MCA[C3][A2]得到的。其中第一项为0;第二项 M A B C [ A 2 ] [ C 2 ] × M C A [ C 2 ] [ A 2 ] = 2 × 1 = 2 M_{ABC}[A_2][C_2]\times M_{CA}[C_2][A_2]=2\times 1=2 MABC[A2][C2]×MCA[C2][A2]=2×1=2表示有2条 A 2 → B → C 2 A_2\rightarrow B\rightarrow C_2 A2BC2路径和1条 C 2 → A 2 C_2\rightarrow A_2 C2A2路径组合成2条 A 2 → B → C → A 2 A_2\rightarrow B\rightarrow C \rightarrow A_2 A2BCA2路径;第三项 M A B C [ A 2 ] [ C 3 ] × M C A [ C 3 ] [ A 2 ] = 1 × 1 = 1 M_{ABC}[A_2][C_3]\times M_{CA}[C_3][A_2]=1\times 1=1 MABC[A2][C3]×MCA[C3][A2]=1×1=1表示有1条 A 2 → B → C 3 A_2\rightarrow B\rightarrow C_3 A2BC3路径和1条 C 3 → A 2 C_3\rightarrow A_2 C3A2路径组合成1条 A 2 → B → C → A 2 A_2\rightarrow B\rightarrow C \rightarrow A_2 A2BCA2路径。因此图中后面三个 A 3 A_3 A3节点前面应该分别连 C 2 , C 2 , C 3 C_2,C_2,C_3 C2,C2,C3节点。

在这里插入图片描述

​ 这里可以看到, M C A M_{CA} MCA矩阵中有用的是每一列中数字为1的行数,可以提前用一个map来存储,避免循环搜索,在矩阵比较稀疏的时候会大量节省时间。另外,这一步中 M A B C A M_{ABCA} MABCA矩阵中 [ A 1 ] [ A 1 ] , [ A 2 ] [ A 2 ] [A_1][A_1],[A_2][A_2] [A1][A1],[A2][A2]这两个位置已经用完了,将其移出队列,而新的有效的位置为 M A B C M_{ABC} MABC矩阵中的 [ A 1 ] [ C 1 ] , [ A 2 ] [ C 2 ] , [ A 2 ] [ C 3 ] [A_1][C_1],[A_2][C_2],[A_2][C_3] [A1][C1],[A2][C2],[A2][C3],因为我们用到了其对应的1,2,1三个数字,下一步再往前推时要考虑这三个数字的由来。

​ 接下来继续往前推,为了找到连在 C C C类节点前面的 B B B类节点,需要用到 M A B , M B C M_{AB},M_{BC} MAB,MBC矩阵。


M A B C = M A B × M B C = M A B B 1 B 2 A 1 1 0 A 2 1 1 × M B C C 1 C 2 C 3 B 1 1 1 0 B 2 0 1 1 = M A B C C 1 C 2 C 3 A 1 1 1 0 A 2 1 2 1 M_{ABC}=M_{AB}\times M_{BC}= \begin{array}{c|cc} M_{AB}& B_1 & B_2 \\ \hline A_1 & 1 & 0 \\ A_2 & 1 & 1 \end{array} \times \begin{array}{c|ccc} M_{BC} & C_1 & C_2 & C_3 \\ \hline B_1 & 1 & 1 & 0 \\ B_2 & 0 & 1 & 1 \end{array} = \begin{array}{c|ccc} M_{ABC} & C_1 & C_2 & C_3 \\ \hline A_1 & 1 & 1 & 0 \\ A_2 & 1 & 2 & 1 \end{array} MABC=MAB×MBC=MABA1A2B111B201×MBCB1B2C110C211C301=MABCA1A2C111C212C301


​ 由上一步可知,这里有效的路径数是 M A B C [ A 1 ] [ C 1 ] , M A B C [ A 2 ] [ C 2 ] , M A B C [ A 2 ] [ C 3 ] M_{ABC}[A_1][C_1],M_{ABC}[A_2][C_2],M_{ABC}[A_2][C_3] MABC[A1][C1],MABC[A2][C2],MABC[A2][C3],将这三个数字用完全相同的方法可得前面连接的 B B B类节点应分别为 { B 1 } , { B 1 , B 2 } , { B 2 } \{B_1\},\{B_1,B_2\},\{B_2\} {B1},{B1,B2},{B2}

在这里插入图片描述

​ 到这一步实际上已经把4条环都找出来了,将首尾相连即可,结果与前面列出的相同~

在这里插入图片描述

4 总结

​ 这个算法实际上是搜索出所有特定结构的路径,环是一种特殊的路径,因此也可以找出来。在给定一个网络时,先按节点类型排列并构建邻接矩阵,可以搜索出任意一个长度和结构的路径。

​ 假设一个网络有 q q q类节点,网络节点总数为 N N N,且每类节点数量相同,要搜索长度为 l l l的路径,需要矩阵相乘 ( l − 1 ) (l-1) (l1)次,因此时间复杂度为 O ( ( l − 1 ) ( N q ) 3 ) O((l-1)(\frac{N}{q})^3) O((l1)(qN)3),这是在完全不考虑矩阵相乘的优化的情况下。假如最终找到了 M M M条路径,在往回推逐个找到具体节点的过程中,时间复杂度为 O ( l M ) O(lM) O(lM)。如果各类节点数量不太平均的话,矩阵相乘的复杂度就要具体情况具体分析了,当然也很容易~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值