Eu fiz algumas pesquisas e parece que falta uma pequena parte desse algoritmo. Entendo como uma Pesquisa de Largura Primeiro funciona, mas não entendo exatamente como ela me levará a um caminho específico, em vez de apenas me dizer para onde cada nó individual pode ir. Acho que a maneira mais fácil de explicar minha confusão é fornecer um exemplo:
Por exemplo, digamos que eu tenha um gráfico como este:
E meu objetivo é ir de A a E (todas as arestas não têm peso).
Começo em A, porque essa é minha origem. Enfileiro em A, seguido de desenfileirar imediatamente A e explorá-lo. Isso produz B e D, porque A está conectado a B e D. Assim, enfileiramos B e D.
Retirar a fila de B e explorá-la, e descobrir que ela leva a A (já explorada) e C, então enfileirar C. Em seguida, desenfileirar D e descobrir que isso leva a E, meu objetivo. Em seguida, retiro a fila de C e acho que isso também leva a E, meu objetivo.
Sei logicamente que o caminho mais rápido é A-> D-> E, mas não tenho certeza de como exatamente a primeira pesquisa ajuda - como devo gravar caminhos de modo que, quando terminar, possa analisar os resultados e ver que o caminho mais curto é A-> D-> E?
Além disso, observe que na verdade não estou usando uma árvore, portanto, não há nós "pais", apenas filhos.
Respostas:
Tecnicamente, a pesquisa por largura da primeira (BFS) por si só não permite encontrar o caminho mais curto, simplesmente porque o BFS não está procurando o caminho mais curto: o BFS descreve uma estratégia para pesquisar em um gráfico, mas não diz que você deve procurar alguma coisa em particular.
Algoritmo de Dijkstra adapta o BFS para permitir encontrar os caminhos mais curtos de fonte única.
Para recuperar o caminho mais curto da origem para um nó, é necessário manter dois itens para cada nó no gráfico: a menor distância atual e o nó anterior no caminho mais curto. Inicialmente, todas as distâncias são definidas como infinito e todos os predecessores são definidos como vazios. No seu exemplo, você define a distância de A como zero e prossegue com o BFS. Em cada etapa, você verifica se pode melhorar a distância de um descendente, ou seja, a distância da origem ao predecessor mais o comprimento da borda que você está explorando é menor que a melhor distância atual para o nó em questão. Se você puder melhorar a distância, defina o novo caminho mais curto e lembre-se do predecessor pelo qual esse caminho foi adquirido. Quando a fila BFS estiver vazia, escolha um nó (no seu exemplo, é E) e retorne seus predecessores de volta à origem.
Se isso parecer um pouco confuso, a wikipedia possui uma boa seção de pseudocódigo sobre o tópico.
fonte
Como apontado acima, o BFS pode ser usado apenas para encontrar o caminho mais curto em um gráfico se:
Não há loops
Todas as arestas têm o mesmo peso ou nenhum peso.
Para encontrar o caminho mais curto, tudo o que você precisa fazer é iniciar a partir da fonte e realizar uma primeira pesquisa abrangente e parar quando encontrar o Nó de destino. A única coisa adicional que você precisa fazer é ter uma matriz anterior [n] que armazene o nó anterior para cada nó visitado. O anterior da origem pode ser nulo.
Para imprimir o caminho, faça um loop simples através da matriz [] anterior da origem até chegar ao destino e imprimir os nós. O DFS também pode ser usado para encontrar o caminho mais curto em um gráfico em condições semelhantes.
No entanto, se o gráfico for mais complexo, contendo arestas e loops ponderados, precisamos de uma versão mais sofisticada do BFS, ou seja, o algoritmo de Dijkstra.
fonte
To print the path, simple loop through the previous[] array from source till you reach destination.
Mas anterior da fonte é nulo. Eu acho que o que você quis dizer ébacktrace from destination using the previous array until you reach the source
.Do tutorial aqui
fonte
Eu perdi 3 dias
finalmente resolvi uma questão gráfica
usada para
encontrar a menor distância
usando o BFS
Deseja compartilhar a experiência.
Perdi três dias tentando todas as alternativas acima, verificando e revendo novamente e novamente acima,
elas não são o problema.
(Tente gastar tempo procurando outros problemas, se não encontrar nenhum problema acima de 5).
Mais explicações do comentário abaixo:
Suponha que acima é o seu gráfico
seja descendente.
Para A, os adjacentes são B e C.
Para B, os adjacentes são D e E.
Para C, os adjacentes são F e G
digamos, o nó inicial é A
quando você alcança A, para, B e C, a menor distância entre B e C de A é 1
quando você alcança D ou E, através de B, a distância mais curta de A e D é 2 (A-> B-> D)
da mesma forma, A-> E é 2 (A-> B-> E)
também, A-> F & A-> G é 2
Portanto, agora, em vez de 1 distância entre nós, se for 6, basta multiplicar a resposta por 6
exemplo,
se a distância entre cada um for 1, então A-> E é 2 (A-> B-> E = 1 + 1 )
se a distância entre cada um é 6, então A-> E é 12 (A-> B-> E = 6 + 6)
sim, o bfs pode seguir qualquer caminho
mas estamos calculando para todos os caminhos
se você tem que ir de A a Z, então nós viajamos todos os caminhos de A a um intermediário I, e uma vez que haverá muitos caminhos que descartar tudo, mas caminho mais curto até que eu, em seguida, continuar com o caminho mais curto à frente para o próximo nó J
novamente se existem vários caminhos de I a J, tomamos apenas o menor
exemplo,
suponha,
A -> eu temos a distância 5
(STEP) assuma, I -> J temos vários caminhos, das distâncias 7 e 8, já que 7 é o menor
tomamos A -> J como 5 (A-> eu menor) + 8 (menor agora) = 13,
então A-> J é agora 13
, repetimos agora acima (STEP) para J -> K e assim por diante, até chegarmos para Z
Leia esta parte, 2 ou 3 vezes, e desenhe no papel, você certamente entenderá o que estou dizendo, boa sorte
fonte
Com base na resposta acheron55 , postei uma possível implementação aqui .
Aqui está um breve verão:
Tudo o que você precisa fazer é acompanhar o caminho pelo qual o objetivo foi alcançado. Uma maneira simples de fazer isso é entrar no
Queue
caminho inteiro usado para alcançar um nó, e não no próprio nó.O benefício de fazer isso é que, quando o destino é atingido, a fila mantém o caminho usado para alcançá-lo.
Isso também é aplicável aos gráficos cíclicos, nos quais um nó pode ter mais de um pai.
fonte
Visitando este tópico após algum período de inatividade, mas como não vejo uma resposta completa, aqui estão meus dois centavos.
A busca pela largura da primeira sempre encontrará o caminho mais curto em um gráfico não ponderado. O gráfico pode ser cíclico ou acíclico.
Veja abaixo o pseudocódigo. Esse pseudocódigo pressupõe que você esteja usando uma fila para implementar o BFS. Ele também pressupõe que você pode marcar vértices como visitados e que cada vértice armazena um parâmetro de distância, que é inicializado para o infinito.
Observe que essa abordagem não funciona para gráficos ponderados - para isso, consulte o algoritmo de Dijkstra.
fonte
A solução a seguir funciona para todos os casos de teste.
fonte