我正在尝试将无向树划分为两个子树,每个子树都连接在一起。我的理解是,这可以使用描述here所述的Fiedler向量来完成。但是,当我按照这个过程时,结果子树没有连接。
我用来实现二分的代码如下,并且未能平分的树被定义为here。
import networkx as nx
from itertools import compress
g = nx.from_dict_of_dicts(broken_g)
def split_graph(graph):
"""Split a graph into two pieces using the Fiedler vector.
See https://en.wikipedia.org/wiki/Graph_partition#Fiedler_eigenvalue_and_eigenvector
"""
assert nx.is_connected(graph), 'must pass connected graph'
fiedler_vec = nx.fiedler_vector(graph, normalized=True, weight=False)
mask_a = fiedler_vec > 0
mask_b = ~ mask_a
subgraph_a_nodes = compress(graph.nodes(), mask_a)
subgraph_b_nodes = compress(graph.nodes(), mask_b)
subgraph_a = graph.subgraph(subgraph_a_nodes)
subgraph_b = graph.subgraph(subgraph_b_nodes)
assert nx.is_connected(subgraph_a) and nx.is_connected(subgraph_b), 'split did not produce connected subgraphs'
return [subgraph_a, subgraph_b]
split_graph(g)
当我运行时,所得到的子树都没有连接 - 每个子树都有一个或两个大的连接组件和几个孤立的节点。绘制Fiedler向量的值并识别孤立的节点如下所示:
这到底是怎么回事?
答案 0 :(得分:0)
树的一个特征是树中每对顶点之间只有一条路径。因此,当切割边缘时,该边缘上的顶点不再连接,因为这是它们唯一的路径。由于连通性是可交换的,因此切口一侧的每个顶点都与切口另一侧的每个顶点断开连接。结果是,当您剪切单个边时,始终将树分割为两个连接的子树。看一下这个维基百科页面,看起来使用光谱二分法可能会产生削减多个边缘的解决方案。基本上任何削减超过1个边缘的二分法都会产生超过2个连接的子树。