我试图找到一个快速算法,以获得所有连接的子图形成一个子图长度受限的无向图。简单的方法,例如来自每个顶点的BFS或DFS会产生大量的等于子图,因此在每次算法迭代中我们都必须修剪子图集。我在俄罗斯数学论坛an algorithm找到了:
Procedure F(X,Y)
//X set of included vertices
//Y set of forbidden vertices to construct new subgraph
1.if |X|=k, then return;
2.construct a set T[X] of vertices that adjacent to vertices from X (If X is a empty set, than T[X]=V), but not belong to the sets X,Y;
3.Y1=Y;
4.Foreach v from T[X] do:
__4.1.X1=X+v;
__4.2.show subgraph X1;
__4.3.F(X1,Y1);
__4.4.Y1=Y1+v;
Initial call F(X,Y):
X, Y = empty set;
F(X,Y);
这个算法的主要思想是使用“禁止集”,因此,这个不需要修剪,这个算法的作者说它比基于修剪等于子图的解决方案快300倍。但我没有找到任何证据证明这个算法是正确的。
更新: 找到了更有效的解决方案here
答案 0 :(得分:2)
以下是我认为是您原始算法的Python实现:
from collections import defaultdict
D=defaultdict(list)
def addedge(a,b):
D[a].append(b)
D[b].append(a)
addedge(1,2)
addedge(2,3)
addedge(3,4)
V=D.keys()
k=2
def F(X,Y):
if len(X)==k:
return
if X:
T = set(a for x in X for a in D[x] if a not in Y and a not in X)
else:
T = V
Y1=set(Y)
for v in T:
X.add(v)
print X
F(X,Y1)
X.remove(v)
Y1.add(v)
print 'original method'
F(set(),set())
F生成大小为< = k的所有连通子图,其中子图必须包含X中的顶点(连接的子图本身),并且不得在Y中包含顶点。
我们知道要在子图中包含另一个顶点,我们必须使用连接的顶点,这样我们就可以根据最终子图内的第一个连接顶点v的标识进行递归。禁止集意味着我们确保无法生成子图的第二个副本,因为此副本必须使用v,但v在禁用集中,因此不能再次使用。
因此,在这种肤浅的分析水平上,这种算法看似高效且正确。
答案 1 :(得分:0)
您没有很好地描述算法。我们不知道k是这个算法中的V是什么或者是什么。我只假设k是子图上的受限长度,V是某个根顶点。
如果这是真的,那么我认为这个算法不正确。假设我们有一个只有两个连接顶点v1,v2和受限制的子图k = 1的图。
在第一次迭代中:X,Y =空,T(X)= {v1},X1 = {V1},Y1 =空,我们显示X1。
现在回到第一次迭代Y(1)= v1。循环结束,初始调用也在这里结束。所以我们只打印出X1。我们打算打印出X1,X2。
顺便说一句,不要“测试”算法 - 没有办法测试它(可能的测试用例的数量是无限的)。你确实应该正式证明它。