Considere un gráfico conectado no dirigido. Un conjunto de aristas coincidentes en este gráfico se define como un conjunto de aristas de modo que no haya dos aristas en el conjunto que compartan un vértice común. Por ejemplo, la figura izquierda denota un conjunto coincidente en verde, mientras que la figura derecha denota un conjunto no coincidente en rojo.
Se dice que un conjunto coincidente es maximally matching
, o a maximal matching
si es imposible agregar otro borde del gráfico al conjunto coincidente. Por lo tanto, los dos ejemplos anteriores no son conjuntos de coincidencia máxima, pero los dos conjuntos a continuación en azul son coincidencias máximas. Tenga en cuenta que las coincidencias máximas no son necesariamente únicas. Además, no se exige que el tamaño de cada coincidencia máxima posible para un gráfico sea igual a otra coincidencia.
El objetivo de este desafío es escribir un programa / función para encontrar una coincidencia máxima de un gráfico.
Entrada
Suponga que todos los vértices del gráfico de entrada tienen una numeración entera consecutiva que comienza en cualquier valor entero inicial que elija. Un borde se describe mediante un par de enteros desordenados que denotan los vértices que conecta el borde. Por ejemplo, el gráfico que se muestra arriba podría describirse con el siguiente conjunto desordenado de aristas (suponiendo que la numeración de vértices comienza en 0):
[(0,1), (0,2), (1,3), (1,4), (2,3), (3,4), (3,5), (5,6)]
Una forma alternativa de describir un gráfico es a través de una lista de adyacencia. Aquí hay un ejemplo de lista de adyacencia para el gráfico anterior:
[0:(1,2), 1:(0,3,4), 2:(0,3), 3:(1,2,4,5), 4:(1,3), 5:(3,6), 6:(5)]
Su programa / función debe tomar como entrada un gráfico de cualquier fuente (stdio, parámetro de función, etc.). Puede usar cualquier notación deseada siempre que no se comunique información no trivial adicional a su programa. Por ejemplo, tener un parámetro adicional que indique el número de bordes de entrada es perfectamente aceptable. De manera similar, pasar un conjunto múltiple de bordes desordenado, una lista de adyacencia o una matriz de adyacencia está bien.
Puedes asumir:
- El gráfico está conectado (por ejemplo, es posible alcanzar cualquier vértice dado cualquier vértice inicial).
- Hay al menos un borde.
- Un borde nunca conecta un vértice directamente a sí mismo (por ejemplo, el borde
(1,1)
no se dará como entrada). Tenga en cuenta que los ciclos aún son posibles (p. Ej .: los gráficos anteriores). - Puede requerir que los vértices de entrada comiencen en cualquier índice (por ejemplo, el primer vértice puede ser 0, 1, -1, etc.).
- La numeración de vértices aumenta secuencialmente desde el índice inicial elegido (por ejemplo
1,2,3,4,...
, o0,1,2,3,...
).
Salida
Su programa / función debería generar una lista de bordes que denota un conjunto de coincidencia máxima. Un borde se define por los dos vértices que ese borde conecta. Ex. salida para el conjunto azul izquierdo (usando el ejemplo de ordenamiento de vértices de entrada):
[(1,4), (2,3), (5,6)]
Tenga en cuenta que el orden de los vértices no es importante; Entonces, el siguiente resultado describe el mismo conjunto coincidente:
[(4,1), (2,3), (6,5)]
La salida puede ser stdout, un archivo, valor de retorno de función, etc.
Ejemplos
Aquí hay algunas entradas de ejemplo (usando el formato de lista de adyacencia). Estos ejemplos comienzan a contar vértices en 0
.
Tenga en cuenta que no se proporcionan resultados de ejemplo, sino que he incluido un código de validación de 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)]
Código de validación Python 3
Aquí hay un código de validación de Python 3 que toma un gráfico y un conjunto de bordes e imprime si ese conjunto coincide al máximo o no. Este código funciona con cualquier índice de inicio de vértice.
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
Ejemplo de uso:
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
Puntuación
Este es el código de golf; el código más corto gana. Se aplican lagunas estándar. Puede usar los complementos deseados.
[[0 1] [3 4]]
lugar del conjunto máximo[[0 2] [1 4] [3 5]]
. (Estoy ignorando el(1, 1)
borde que parece estar allí por error)