算法问题

时间:2010-01-01 17:32:16

标签: algorithm clique clique-problem

图形是图形的子图形,其中任何顶点与其余顶点连接。

在k-问题中,输入是无向图和数字k,输出是clof大小k(如果存在)(或者,有时,大小为k的所有cl)

2 个答案:

答案 0 :(得分:3)

假设不失一般性,图的节点由0和N-1之间的整数标识(不失一般性,因为如果每个节点需要携带其他信息,则可以有N节点的数组/向量/列表对象,并将这些整数作为索引到有问题的数组中)。例如,可以使用从每个节点到作为节点的直接邻居的集合的映射来指示图的连通性。

要检查连接,而不是立即邻接,您宁愿需要一个不同的映射 - 即时邻居映射的transitive closure。当然有很好的算法(参见例如networkx包的Python源代码),但是一个暴力的算法只是将立即邻接映射复制到连接映射,然后迭代扩展设置,直到一次迭代不再展开任何集合。

,例如,Python 2.6暴力示例:

import copy

def transitive_closure(immediate_neighbors):
  result = copy.deepcopy(immediate_neighbors)
  changes = True
  while changes:
    changes = False
    for node in result:
      newset = set(result[node])
      for neighbor in result[node]:
        newset.update(result[neighbor])
      if newset != result[node]:
        changes = True
        result[node] = newset
  return result

immediate = {0:[1,2], 1:[0], 2:[0], 3:[4], 4:[3]}
connections = transitive_closure(immediate)
for node in sorted(connections):
  print node, sorted(connections[node])

打印:

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

使用connections字典,我们所要做的就是检查k个节点的每个组合(例如,在Python 2.6或更高版本中,itertools.combinations(range(N), k)为我们提供这些组合) :如果它是连接到任何一个成员的项目集的一个子集(当然不一定是正确的子集),那将是一个集团。

例如,上面的代码可以继续,以显示所有2个派系:

import itertools
cliques = set()
for somenodes in itertools.combinations(range(5), 2):
  if set(somenodes) <= connections[somenodes[0]]:
    cliques.add(somenodes)
print '%d cliques:' % len(cliques)
for c in sorted(cliques): print ' ', c

使用前一个示例中使用的数据进行打印:

4 cliques:
  (0, 1)
  (0, 2)
  (1, 2)
  (3, 4)

对于 -brute force方法,我建议再次研究我之前指出的networkx源代码。

答案 1 :(得分:0)

好的,数字顶点1 ... n并将图形转换为布尔邻接矩阵 - 1(i,j)意味着i和j连接。在无向图中,矩阵应该是对称的。现在你的任务减少到找到一个大小为k x k且全1的“子方形”。 “子方块”很有趣,因为行和列不需要彼此相邻。要获得一些子平方,你可以从n行,n列开始,消除(n-k)行和列 - 瞧!你懂了。

现在,所有1的每个独特子广场都将对应一个集团。要检查唯一性,请将子方形表示为不可变元组((i1,j1),(i2,j2)...(ik,jk))(Python表示法)。

在Python中,您可以将元组添加到无序集合,并询问集合是否已包含我们要搜索的元素。