码
基于@MBo的出色答案,这是使用networkx进行二部图匹配的实现。
import networkx as nx
def is_potentially_divisible(multiples, divisors):
if len(multiples) != len(divisors):
return False
g = nx.Graph()
g.add_nodes_from([('A', a, i) for i, a in enumerate(multiples)], bipartite=0)
g.add_nodes_from([('B', b, j) for j, b in enumerate(divisors)], bipartite=1)
edges = [(('A', a, i), ('B', b, j)) for i, a in enumerate(multiples)
for j, b in enumerate(divisors) if a % b == 0]
g.add_edges_from(edges)
m = nx.bipartite.maximum_matching(g)
return len(m) // 2 == len(multiples)
print(is_potentially_divisible([6, 12, 8], [3, 4, 6]))
print(is_potentially_divisible([6, 12, 8], [3, 4, 3]))
print(is_potentially_divisible([10, 12, 6, 5, 21, 25], [2, 7, 5, 3, 12, 3]))
笔记
根据文档:
maximum_matching()返回的字典包含左顶点集和右顶点集中顶点的映射。
这意味着,返回的字典应该是两倍大A
和B
。
节点从
[10, 12, 6, 5, 21, 25]
至:
[('A', 10, 0), ('A', 12, 1), ('A', 6, 2), ('A', 5, 3), ('A', 21, 4), ('A', 25, 5)]
为了避免A
和之间的节点之间发生冲突B
。还添加了id,以使节点在重复的情况下保持不同。
效率
该maximum_matching
方法使用Hopcroft-Karp算法,该算法O(n**2.5)
在最坏的情况下运行。图的生成是O(n**2)
,因此整个方法都在中运行O(n**2.5)
。它在大型阵列上应该可以正常工作。排列解决方案是O(n!)
并且将无法处理具有20个元素的数组。
有图
如果您对显示最佳匹配的图表感兴趣,可以混合使用matplotlib和networkx:
import networkx as nx
import matplotlib.pyplot as plt
def is_potentially_divisible(multiples, divisors):
if len(multiples) != len(divisors):
return False
g = nx.Graph()
l = [('l', a, i) for i, a in enumerate(multiples)]
r = [('r', b, j) for j, b in enumerate(divisors)]
g.add_nodes_from(l, bipartite=0)
g.add_nodes_from(r, bipartite=1)
edges = [(a,b) for a in l for b in r if a[1] % b[1]== 0]
g.add_edges_from(edges)
pos = {}
pos.update((node, (1, index)) for index, node in enumerate(l))
pos.update((node, (2, index)) for index, node in enumerate(r))
m = nx.bipartite.maximum_matching(g)
colors = ['blue' if m.get(a) == b else 'gray' for a,b in edges]
nx.draw_networkx(g, pos=pos, arrows=False, labels = {n:n[1] for n in g.nodes()}, edge_color=colors)
plt.axis('off')
plt.show()
return len(m) // 2 == len(multiples)
print(is_potentially_divisible([6, 12, 8], [3, 4, 6]))
print(is_potentially_divisible([6, 12, 8], [3, 4, 3]))
print(is_potentially_divisible([10, 12, 6, 5, 21, 25], [2, 7, 5, 3, 12, 3]))
这是相应的图: