La larghezza dell'albero di un grafico non orientato è un concetto molto importante nella teoria dei grafi. Sono state inventate tonnellate di algoritmi grafici che funzionano velocemente se si dispone di una decomposizione del grafico con una piccola larghezza dell'albero.
La larghezza degli alberi è spesso definita in termini di decomposizioni degli alberi. Ecco un grafico e una scomposizione dell'albero di quel grafico, per gentile concessione di Wikipedia:
Una decomposizione dell'albero è un albero in cui ogni vertice è associato a un sottoinsieme dei vertici del grafico originale, con le seguenti proprietà:
- Ogni vertice nel grafico originale si trova in almeno uno dei sottoinsiemi.
- Ogni bordo nel grafico originale ha entrambi i suoi vertici in almeno uno dei sottoinsiemi.
- Tutti i vertici nella decomposizione i cui sottoinsiemi contengono un dato vertice originale sono collegati.
Puoi verificare che la decomposizione sopra segua queste regole. La larghezza di una decomposizione dell'albero è la dimensione del suo sottoinsieme più grande, meno uno. Pertanto, è due per la decomposizione sopra. La larghezza dell'albero di un grafico è la larghezza più piccola di qualsiasi decomposizione dell'albero di quel grafico.
In questa sfida, ti verrà dato un grafico connesso e non orientato e dovrai trovare la sua larghezza dell'albero.
Mentre trovare le decomposizioni degli alberi è difficile, ci sono altri modi per calcolare la larghezza degli alberi. La pagina di Wikipedia ha più informazioni, ma un metodo di calcolo della larghezza dell'albero non menzionato qui che viene spesso utilizzato negli algoritmi per calcolare la larghezza dell'albero è la larghezza minima di ordinazione di eliminazione. Vedi qui per un documento che utilizza questo fatto.
In un ordine di eliminazione, si eliminano tutti i vertici di un grafico uno alla volta. Quando ogni vertice viene eliminato, i bordi vengono aggiunti collegando tutti i vicini di quel vertice tra loro. Questo si ripete fino a quando tutti i vertici non sono spariti. La larghezza dell'ordine di eliminazione è il maggior numero di vicini che qualsiasi vertice che viene eliminato ha durante questo processo. La larghezza dell'albero è uguale al minimo su tutti gli ordini della larghezza degli ordini di eliminazione. Ecco un programma di esempio che utilizza questo fatto per calcolare la larghezza dell'albero:
import itertools
def elimination_width(graph):
max_neighbors = 0
for i in sorted(set(itertools.chain.from_iterable(graph))):
neighbors = set([a for (a, b) in graph if b == i] + [b for (a, b) in graph if a == i])
max_neighbors = max(len(neighbors), max_neighbors)
graph = [edge for edge in graph if i not in edge] + [(a, b) for a in neighbors for b in neighbors if a < b]
return max_neighbors
def treewidth(graph):
vertices = list(set(itertools.chain.from_iterable(graph)))
min_width = len(vertices)
for permutation in itertools.permutations(vertices):
new_graph = [(permutation[vertices.index(a)], permutation[vertices.index(b)]) for (a, b) in graph]
min_width = min(elimination_width(new_graph), min_width)
return min_width
if __name__ == '__main__':
graph = [('a', 'b'), ('a', 'c'), ('b', 'c'), ('b', 'e'), ('b', 'f'), ('b', 'g'),
('c', 'd'), ('c', 'e'), ('d', 'e'), ('e', 'g'), ('e', 'h'), ('f', 'g'), ('g', 'h')]
print(treewidth(graph))
Esempi:
[(0, 1), (0, 2), (0, 3), (2, 4), (3, 5)]
1
[(0, 1), (0, 2), (1, 2), (1, 4), (1, 5), (1, 6), (2, 3), (2, 4), (3, 4), (4, 6), (4, 7), (5, 6), (6, 7)]
2
[(0, 1), (0, 3), (1, 2), (1, 4), (2, 5), (3, 4), (3, 6), (4, 5), (4, 7), (5, 8), (6, 7), (7, 8)]
3
[(0, 1), (0, 2), (0, 3), (0, 4), (1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4)]
4
Riceverai il grafico come input e dovrai restituire la larghezza dell'albero come output. Il formato di input è flessibile. È possibile prendere un elenco di spigoli, una mappa di adiacenza o una matrice di adiacenza come input. Se desideri utilizzare un altro formato di input, chiedi nei commenti. È possibile supporre che l'input sia collegato e che tale assunzione possa essere incorporata nel formato di input, ad esempio utilizzando un elenco di spigoli.
EDIT: le operazioni integrate che calcolano la larghezza dell'albero non sono consentite. Mi scuso per non aver specificato questo in anticipo.
Il codice più corto vince.
(V,E)
, questo sarebbe un input valido?