Existe esse algoritmo padrão para encontrar o caminho mais longo em árvores não direcionadas usando duas pesquisas profundas:
- Inicie o DFS a partir de um vértice aleatório e encontre o vértice mais distante dele; diga que é .v ′
- Agora inicie um DFS a partir de para encontrar o vértice mais distante dele. Esse caminho é o caminho mais longo do gráfico.
A questão é: isso pode ser feito com mais eficiência? Podemos fazer isso com um único DFS ou BFS?
(Isso pode ser descrito de maneira equivalente como o problema de calcular o diâmetro de uma árvore não direcionada.)
algorithms
graphs
trees
emmy
fonte
fonte
Respostas:
Realizamos uma pesquisa profunda em ordem de pós e agregamos resultados no caminho, ou seja, resolvemos o problema recursivamente.
Para cada nó com filhos (na árvore de pesquisa), existem dois casos:u 1 , ... , u kv u1,…,uk
No segundo caso, temos que combinar os um ou dois caminhos mais longos de em uma das subárvores; estes são certamente aqueles das folhas mais profundas. O comprimento do caminho é então se , ou se , com o conjunto múltiplo de alturas das subárvores¹.H ( k ) + H ( k - 1 ) + 2 k > 1 H ( k ) + 1 k = 1 H = { h ( T u i ) ∣ i = 1 , … , k }v H(k)+H(k−1)+2 k>1 H(k)+1 k=1 H={h(Tui)∣i=1,…,k}
No pseudo-código, o algoritmo se parece com isso:
fonte
height1 + height2
é o comprimento desse caminho. Se é realmente o caminho mais longo, é escolhido pormax
. Também é explicado no texto acima, então não vejo seu problema? Certamente, você deve recuar para descobrir se esse é realmente o caminho mais longo e, mesmo que não, não dói (correção correta) recuar.height2
remove explicitamenteheight1
da consideração, então como ele pode escolher o mesmo filho duas vezes? Isso também foi explicado no texto introdutório.longestPathHeight(T)
retornasse um par(h,d)
, ondeh
é a alturaT
ed
o diâmetro deT
. (Direito?)Isso pode ser resolvido de uma maneira melhor. Além disso, podemos reduzir a complexidade do tempo para O (n) com uma ligeira modificação na estrutura de dados e usando uma abordagem iterativa. Para uma análise detalhada e várias maneiras de resolver esse problema com várias estruturas de dados.
Aqui está um resumo do que eu quero explicar em uma postagem no meu blog :
Abordagem recursiva - diâmetro da árvore Outra maneira de abordar esse problema é a seguinte. Como mencionamos acima, o diâmetro pode
O que significa que o diâmetro pode ser idealmente derivado por
E sabemos que o diâmetro é o caminho mais longo, por isso tomamos o máximo de 1 e 2, caso esteja do lado ou de 3, se atravessarmos a raiz.
Abordagem Iterativa - Diâmetro da Árvore
Temos uma árvore, precisamos de uma meta informação com cada nó para que cada nó saiba o seguinte:
Uma vez que cada nó tem essas informações, precisamos de uma variável temporária para acompanhar o caminho máximo. Quando o algoritmo termina, temos o valor do diâmetro na variável temp.
Agora, precisamos resolver esse problema em uma abordagem de baixo para cima, porque não temos idéia dos três valores para a raiz. Mas conhecemos esses valores para as folhas.
Passos para resolver
Em um determinado nó,
fonte
Abaixo está o código que retorna um caminho de diâmetro usando apenas uma única passagem DFS. Requer espaço extra para acompanhar o melhor diâmetro visto até o momento e o caminho mais longo, começando em um nó específico da árvore. Essa é uma abordagem de programação dinâmica baseada no fato de que um caminho de diâmetro mais longo não inclui raiz ou é a combinação dos dois caminhos mais longos dos vizinhos da raiz. Portanto, precisamos de dois vetores para acompanhar essas informações.
fonte