考虑一个连接的无向图。甲边缘的匹配组在此图被定义为一组边,使得在该组共享的任何两个边缘公共顶点的。例如,左图表示绿色的匹配集,而右图表示红色的不匹配集。
匹配集称为maximally matching
,maximal matching
如果不可能将图的另一条边添加到匹配集,则为。因此,以上两个示例都不是最大匹配集,但是下面两个蓝色的集合都是最大匹配。请注意,最大匹配不一定是唯一的。此外,不要求图形的每个可能最大匹配的大小都应等于另一个匹配。
挑战的目标是编写程序/函数以找到图形的最大匹配。
输入值
假设输入图的所有顶点都有一些连续的整数编号,这些编号从您选择的任何起始整数值开始。一条边由表示该边连接的顶点的无序整数对来描述。例如,上面显示的图形可以使用以下无序边集来描述(假设顶点的编号从0开始):
[(0,1), (0,2), (1,3), (1,4), (2,3), (3,4), (3,5), (5,6)]
描述图的另一种方法是通过邻接表。这是上图的邻接表示例:
[0:(1,2), 1:(0,3,4), 2:(0,3), 3:(1,2,4,5), 4:(1,3), 5:(3,6), 6:(5)]
您的程序/函数必须从任何来源(stdio,函数参数等)获取图形作为输入。只要没有其他无关紧要的信息传达给您的程序,您就可以使用所需的任何符号。例如,一个额外的参数表示输入边的数量是完全可以接受的。类似地,传入无序的边,邻接表或邻接矩阵的多集也可以。
您可以假设:
- 图形已连接(例如,可以在给定任何起始顶点的情况下到达任何顶点)。
- 至少有一条边缘。
- 边永远不会将顶点直接连接到自身(例如,边
(1,1)
不会作为输入提供)。请注意,循环仍然可能(例如:上图)。 - 您可能需要输入顶点从任何索引处开始(例如,第一个顶点可以是0、1,-1等)。
- 顶点编号从您选择的起始索引开始按顺序增加(例如:
1,2,3,4,...
或0,1,2,3,...
)。
输出量
您的程序/函数应输出表示最大匹配集的边列表。一条边由该边连接的两个顶点定义。例如 左蓝色组的输出(使用示例输入顶点顺序):
[(1,4), (2,3), (5,6)]
注意,顶点的顺序并不重要。因此,以下输出描述了相同的匹配集:
[(4,1), (2,3), (6,5)]
输出可能是到stdout,文件,函数返回值等。
例子
这是一些示例输入(使用邻接表格式)。这些示例碰巧开始在处计算顶点0
。
请注意,没有给出示例输出,而是提供了Python 3验证代码。
[0:(1), 1:(0)]
[0:(1,2), 1:(0,3,4), 2:(0,3), 3:(1,2,4,5), 4:(1,3), 5:(3,6), 6:(5)]
[0:(1,2), 1:(0,2,3,4,5), 2:(0,1), 3:(1), 4:(1), 5:(1)]
[0:(1,2), 1:(0,2,3), 2:(0,1,4), 3:(1,4,5), 4:(2,3), 5:(3)]
验证Python 3代码
这是一个Python 3验证代码,它接受图形和一组边并打印出该边是否最大匹配。此代码适用于任何顶点起始索引。
def is_maximal_matching(graph, edges):
'''
Determines if the given set of edges is a maximal matching of graph
@param graph a graph specified in adjacency list format
@param edges a list of edges specified as vertex pairs
@return True if edges describes a maximal matching, False otherwise.
Prints out some diagnostic text for why edges is not a maximal matching
'''
graph_vtxs = {k for k,v in graph.items()}
vtxs = {k for k,v in graph.items()}
# check that all vertices are valid and not used multiple times
for e in edges:
if(e[0] in graph_vtxs):
if(e[0] in vtxs):
vtxs.remove(e[0])
else:
print('edge (%d,%d): vertex %d is used by another edge'%(e[0],e[1],e[0]))
return False
else:
print('edge (%d,%d): vertex %d is not in the graph'%(e[0],e[1],e[0]))
return False
if(e[1] in graph_vtxs):
if(e[1] in vtxs):
vtxs.remove(e[1])
else:
print('edge (%d,%d): vertex %d is used by another edge'%(e[0],e[1],e[1]))
return False
else:
print('edge (%d,%d): vertex %d is not in the graph'%(e[0],e[1],e[0]))
return False
if(e[1] not in graph[e[0]]):
print('edge (%d,%d): edge not in graph'%(e[0],e[1]))
return False
# check that any edges can't be added
for v in vtxs:
ovtxs = graph[v]
for ov in ovtxs:
if(ov in vtxs):
print('could add edge (%d,%d) to maximal set'%(v,ov))
return False
return True
用法示例:
graph = {0:[1,2], 1:[0,3,4], 2:[0,3], 3:[1,2,4,5], 4:[1,3], 5:[3,6], 6:[5]}
candidate = [(0,1),(2,3)]
is_maximal_matching(graph, candidate) // False
candidate = [(0,1),(2,3),(5,6),(0,1)]
is_maximal_matching(graph, candidate) // False
candidate = [(0,1),(2,3),(5,6)]
is_maximal_matching(graph, candidate) // True
计分
这是代码高尔夫;最短的代码胜出。有标准漏洞。您可以使用所需的任何内置功能。
[[0 1] [3 4]]
而不是给出了maximal set[[0 2] [1 4] [3 5]]
。(我忽略了(1, 1)
似乎错误地存在的边缘)