Considere um gráfico não direcionado conectado. Um conjunto de arestas correspondente neste gráfico é definido como um conjunto de arestas, de modo que nenhuma duas arestas no conjunto compartilhem um vértice comum. Por exemplo, a figura da esquerda indica um conjunto correspondente em verde, enquanto a figura da direita indica um conjunto não correspondente em vermelho.
Diz- se que maximally matching
um conjunto correspondente é , ou a, maximal matching
se for impossível adicionar outra aresta do gráfico ao conjunto correspondente. Portanto, os dois exemplos acima não são conjuntos de correspondências máximas, mas os dois conjuntos abaixo em azul são correspondências máximas. Observe que as correspondências máximas não são necessariamente únicas. Além disso, não é necessário que o tamanho de cada correspondência máxima possível para um gráfico seja igual a outra correspondência.
O objetivo deste desafio é escrever um programa / função para encontrar uma correspondência máxima de um gráfico.
Entrada
Suponha que todos os vértices do gráfico de entrada tenham uma numeração inteira consecutiva iniciando em qualquer valor inteiro inicial de sua escolha. Uma aresta é descrita por um par não ordenado de números inteiros, indicando os vértices aos quais a aresta se conecta. Por exemplo, o gráfico mostrado acima pode ser descrito com o seguinte conjunto não ordenado de arestas (assumindo que a numeração dos vértices comece em 0):
[(0,1), (0,2), (1,3), (1,4), (2,3), (3,4), (3,5), (5,6)]
Uma maneira alternativa de descrever um gráfico é através de uma lista de adjacências. Aqui está um exemplo de lista de adjacência para o gráfico acima:
[0:(1,2), 1:(0,3,4), 2:(0,3), 3:(1,2,4,5), 4:(1,3), 5:(3,6), 6:(5)]
Seu programa / função deve ter como entrada um gráfico de qualquer fonte (stdio, parâmetro de função, etc.). Você pode usar qualquer notação desejada, desde que nenhuma informação não trivial adicional seja comunicada ao seu programa. Por exemplo, ter um parâmetro extra indicando o número de arestas de entrada é perfeitamente aceitável. Da mesma forma, é bom passar um conjunto múltiplo não ordenado de arestas, lista de adjacências ou matriz de adjacências.
Você pode assumir:
- O gráfico está conectado (por exemplo, é possível alcançar qualquer vértice, dado qualquer vértice inicial).
- Há pelo menos uma aresta.
- Uma aresta nunca conecta um vértice diretamente a ela mesma (por exemplo, a aresta
(1,1)
não será fornecida como entrada). Observe que ainda são possíveis ciclos (por exemplo, os gráficos acima). - Você pode exigir que os vértices de entrada iniciem em qualquer índice (por exemplo, o primeiro vértice pode ser 0, 1, -1 etc.).
- A numeração de vértices aumenta sequencialmente a partir do índice inicial escolhido (por exemplo:
1,2,3,4,...
ou0,1,2,3,...
).
Resultado
Seu programa / função deve exibir uma lista de arestas indicando um conjunto máximo de correspondências. Uma aresta é definida pelos dois vértices aos quais essa aresta se conecta. Ex. saída para o conjunto azul esquerdo (usando o exemplo de pedido de vértice de entrada):
[(1,4), (2,3), (5,6)]
Observe que a ordem dos vértices não é importante; Portanto, a seguinte saída descreve o mesmo conjunto correspondente:
[(4,1), (2,3), (6,5)]
A saída pode ser stdout, um arquivo, valor de retorno da função etc.
Exemplos
Aqui estão algumas entradas de exemplo (usando o formato da lista de adjacências). Esses exemplos começam a contar os vértices em 0
.
Observe que nenhum exemplo de saída é fornecido. Em vez disso, incluí um código de validação do 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 validação Python 3
Aqui está um código de validação do Python 3, que captura um gráfico e um conjunto de arestas e imprime se esse conjunto é o máximo correspondente ou não. Este código funciona com qualquer índice inicial 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
Exemplo 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
Pontuação
Isso é código de golfe; o código mais curto vence. Aplicam-se brechas padrão. Você pode usar quaisquer embutidos desejados.
[[0 1] [3 4]]
vez do conjunto máximo[[0 2] [1 4] [3 5]]
. (Estou ignorando a(1, 1)
vantagem que parecem estar lá por engano)