Sei sulla pagina 1di 16

3.

BUSCA EM GRAFO
1. BUSCA EM PROFUNDIDADE..............................................................................2 Descrio do algoritmo.............................................................................................2 Busca de Articulao................................................................................................4 Ordenao topolgica ..............................................................................................6 Identificao de componentes fortemente conexos .................................................9 2. BUSCA EM LARGURA .......................................................................................13 3. EXERCCIOS ......................................................................................................15

Prof. Ademir Aparecido Constantino Departamento de Informtica Universidade Estadual de Maring.

BUSCA EM GRAFOS
Vrios problemas representados por um grafo podem ser resolvidos efetuando uma busca nesse grafo. s vezes preciso visitar todos os vrtices de um grafos, as vezes o problema pode ser resolvido visitando somente um subconjunto dos vrtices. Consideremos por exemplo o problema do caminho mais curto. Os algoritmos apresentados para resolver esse problema fazem um percurso exaustivo de todos os vrtices. No precisa ser assim se, por exemplo, queremos o caminho mais curto at um vrtice em particular. Nesse caso, assim que ele se encontra no conjunto dos vrtices j visitado, no preciso continuar o algoritmo. Basicamente, existem duas tcnica de busca em grafos: a busca em profundidade (depthfirst search) e a busca em largura (breadth-first search). 1. BUSCA EM PROFUNDIDADE Descrio do algoritmo bsico Seja um grafo G = (V,A) que contm n vrtices. Seja tambm uma representao que indica, para cada vrtice, se ele foi visitado ou no. Eis uma verso recursiva do algoritmo de busca em profundidade que visita todos os vrtices: procedimento Busca(G: Grafo) Para Cada vrtice v de G: Marque v como no visitado Para Cada vrtice v de G: Se v no foi visitado: Busca-Prof(v) procedimento Busca-Prof(v: vrtice) Marque v como visitado Para Cada vrtice w adjacente a v: Se w no foi visitado: Busca-Prof(w)

Note que esse algoritmo funciona com um grafo desconexo. Se j sabemos que o grafo conexo, podemos chamar diretamente a funo Busca-Prof, escolhendo arbitrariamente um vrtice inicial. Complexidade de Tempo: Para implementar esse algoritmo, a estrutura de adjacncia que aparece como candidata ideal, pois a principal operao efetuada pelo algoritmo visitar todos os adjacentes de um vrtice. Supondo ento que a estrutura de adjacncia seja utilizada para implementar a busca, podemos ver que o tempo de execuo do algoritmo em O(m+n)), onde m e n representam o nmero de arestas e de vrtices, respectivamente. Como cada vrtice deve ser visitado, o algoritmo necessariamente far n chamadas do procedimento Busca-Prof, muitas delas recursivas. Em cada chamada, todos os vrtices adjacentes sero testados. No total, o nmero de testes realizados ser igual ao nmero de arestas. Ento o tempo total gasto para as chamadas a Busca-Prof em O(m). Alm disso devemos acrescentar o tempo gasto no 2

procedimento Busca: o tempo de inicializao, e os tempos para testar, para cada vrtice, se ele foi marcado. No total isso d um tempo em O(2n) = O(n). Portanto, o tempo de execuo da busca em profundidade O(m+n)= O(max(m,n)).

Considere agora o grafo ilustrado na figura 1a e a estrutura de adjacncia ilustrada na figuras 1b que representa esse grafo.

Figura 1 Eis o trao de execuo do algoritmo com esse exemplo: Busca-Prof(1) Busca-Prof(2) Busca-Prof(4) Busca-Prof(5) Busca-Prof(3) Busca-Prof(6) Busca-Prof(7) Busca-Prof(8) Quando o algoritmo chega ao vrtice 5, no h nenhum vizinho dele que no foi visitado. Ele retorna dessa chamada para continuar a busca a partir do vrtice anterior que o vrtice 4. A busca continua com o prximo vizinho de 4 que no foi visitado: o vrtice 3. Como o vrtice 3 no tem vizinhos que no foram visitados, o algoritmo retorna imediatamente ao vrtice 4, para continuar a busca com o vrtice 6, e assim por diante chegamos ao ltimo vrtice visitado que vrtice 8. Note que o busca em profundidade resulta numa uma rvore de busca, denotada por T=(V,A'), onde A'A. No exemplo da figura 1, obtemos a rvore de busca ilustrada na figura 2:

Figura 2: rvore de busca identificada pelas arestas em negrito. Vamos ver agora aplicaes da busca em profundidade.

Busca de Articulao Um vrtice em um grafo no direcionado simples e conexo uma articulao se sua remoo torna o grafo resultante desconexo. A identificao de articulao pode ser importante em redes de computadores para identificar os pontos frgeis de uma rede. O algoritmo de busca em profundidade pode ser usado para identificar uma articulao. No grafo da figura 1a, o vrtice 4 uma articulao. Um grafo dito biconexo se ele no contm nenhuma articulao. Vamos agora explicar essencialmente os princpios do algoritmo para procurar as articulaes de um grafo. Primeiro, supomos que tenha sido realizada uma busca em profundidade para obter uma rvore de busca. Essa rvore obtida ser examinada para determinar a existncia de articulao. Vamos ver o que podemos deduzir a partir de cada vrtice x dessa rvore: 1. x a raiz: Se x tem somente um filho, isso significa que qualquer vrtice pode ser alcanado a partir desse filho. Ento, tirando x do grafo no tornaria ele desconexo. Portanto, nesse caso, esse vrtice no uma articulao. Se x tem mais de um filho, isso significa que no podemos alcanar todos os vrtices a partir de algum dos filhos (seno o algoritmo no teria voltado raiz para recomear a busca com outros vizinhos). Nesse caso, obrigatoriamente devemos passar por x para ir de qualquer vrtice de uma subrvore at um vrtice de uma outra subrvore. Portanto, retirar x deixaria o grafo desconexo. 2. x uma folha: Todo vrtice que uma folha da rvore no uma articulao. Isso porque j sabemos que a remoo de um vrtice pendente em uma rvore no a deixa desconexo. 3. x um vrtice interno: Retirando esse vrtice, o grafo fica conexo somente se existir, para cada uma das subrvores de x, uma ligao entre ela e um vrtice ancestral de x. Agora que entendemos o princpio do algoritmo, podemos explic-lo em detalhes. Primeiro, preciso modificar o algoritmo de busca em profundidade para que ele retorne um vetor prenum[1..n] que indica, para cada vrtice do grafo, a sua ordem na pesquisa, e um vetor pred[1..n] define quem o pai de um vrtice na rvore de busca.

procedimento Busca(G: Grafo) pnum := 0 Para Cada vrtice v de G: Marque v como no visitado pnum:=0 pred[v]:=0 Para Cada vrtice v de G: Se v no foi visitado: Busca-Prof(v) procedimento Busca-Prof(v: vrtice) Marque v como visitado pnum := pnum + 1 prenum[v] := pnum Para Cada vrtice w adjacente a v: Se w no foi visitado: pred[w]:=v Busca-Prof(w)

Eis as etapas do algoritmo para identificao de articulao: PASSO 1: Realizar uma busca em profundidade, comeando por qualquer vrtice. Seja T a rvore obtida pelo algoritmo de busca em profundidade. PASSO 2: Identificar, para cada vrtice, um valor que corresponde ordem do primeiro vrtice visitado com o qual ele pode alcanar seguindo arestas de sua subrvore e arestas que no esto na rvore de busca (aresta de retorno). Para identificar esses valores, realizamos um percurso em ps-ordem (ordem inversa a do prenum) na rvore T. Para cada vrtice v, calculamos menor[v] , que representa o mnimo entre: a. prenum[v] ; b. prenum[w] para cada w tal que existe uma aresta (v,w) em G que no petence T; c. menor[x] para cada filho x de v em T. PASSO 3:Agora, as articulaes podem ser facilmente identificadas da seguinte maneira: a. A raiz de T uma articulao se e somente se ela tem mais de um filho; b. Um vrtice v que no a raiz uma articulao se e somente se v tem um filho x tal que menor[x] prenum[v] . Observe que o percurso ps-ordem (Passo 2) pode ser realizado com auxlio de uma pilha, na qual so inseridos os vrtices conforme a ordem de visitas. Portanto, o percurso consiste na retirada dos vrtices da pilha at atingir o vrtice raiz. Note, tambm, que essa pilha pode ser evitada usando a prpria das chamadas recursiva implementado o Passo 2 no fim no algoritmo Busca-Prof. A figura 3 ilustra a aplicao desse algoritmo com o grafo da figura 1a. Est representada a rvore de busca produzida pela busca em profundidade com a ordem de visita de cada vrtice (escrita em ao lado esquerdo do vrtice). Em linha tracejada representam as arestas que ficaram fora da rvore de busca (tambm denominadas de arestas de retorno). Do lado direito de cada vrtice v indicado o valor menor[v] . Podemos conferir que somente 5

dois vrtices tm um filho cujo valor menor[v] maior ou igual sua ordem na busca: os vrtices 4 e 6 que, como podemos verificar, so as nicas articulaes do grafo.

Figura 3: rvore de busca com suas arestas de retorno Vamos ver agora como o algoritmo de busca em profundidade pode ser utilizado para resolver problemas representados com grafos direcionados. Nesses casos, o algoritmo o mesmo. S temos que tomar cuidado com a seleo dos vrtices adjacentes. Num grafo direcionado, um vrtice w adjacente a um vrtice v se existe uma aresta que sai de v e chega em w. Algumas aplicaes so apresentadas nas prximas sees. Ordenao topolgica Se um grafo direcionado G = (V,A) no contm nenhum ciclo, ele induz um conjunto parcialmente ordenado (V, ) tal que para todos vrtices v e w, v w se e somente se existe um caminho de v at w no grafo G. No difcil ver que os vrtices de tal grafo podem ser ordenados (enumerados) para obter uma seqncia de vrtices v1, v2, ..., vn , onde vi vj, para i < j. Essa seqncia uma ordenao topolgica. A seguir sero apresentados trs algoritmos que capaz de fazer a ordenao topolgica. Algoritmo 1 Uma maneira simples de resolver esse problema a utilizao de uma verso do algoritmo de busca em profundidade que imprime o vrtice antes de retornar da chamada. Obteremos assim os vrtices em ordem topolgica invertida:

procedimento Orden-Topo(G: Grafo) Para Cada vrtice v de G: Marque v como no visitado Para Cada vrtice v de G: Se v no foi visitado: Busca-Prof-Orden-Topo(v) procedimento Busca-Prof-Orden-Topo(v: vrtice) Marque v como visitado Para Cada vrtice w adjacente a v: Se w no foi visitado: Busca-Prof-Orden-Topo(w) Imprimir(v) Para verificar que esse algoritmo funciona, s ver o que acontece quando chega ao final de uma recurso, no momento que ele imprime o vrtice. Nesse caso, ele j foi o mais longe possvel a partir do vrtice inicial (isso uma caracterstica do algoritmo de busca em profundidade). Seja x o ltimo vrtice desse caminho. No existe vrtice v tal que x v, porque se for o caso o algoritmo continuaria a busca no mnimo at v. Portanto, de todos os prximos vrtices que sero imprimidos, nenhum sucede a v na ordem, e obteremos uma ordem topolgica invertida. Como exemplo, imagine um currculo de um curso de graduao onde os prrequisitos so expressos por um grafo, como ilustrado na figura 4.

Figura 4 Imaginemos agora uma pessoa que pode se matricular somente em um curso por semestre. Nesse caso, a ordenao topolgica retorna a seqncia de cursos que ela dever fazer. fcil verificar que um resultado possvel do algoritmo a seqncia C5, C8, C6, C3, C4, C1, C7, C2. Invertendo essa seqncia, obtemos a ordem topolgica C2, C7, C1, C4, C3, C6, C8, C5. Note que o resultado depende que qual vrtice selecionado a cada chamada recursiva da busca. Quanto ao tempo de execuo desse algoritmo, claro que na mesma ordem que o algoritmo genrico de busca em profundidade. Algoritmo 2 Existe um outro algoritmo para obter diretamente uma ordenao topolgica de um grafo direcionado. A idia do algoritmo encontrar um vrtice de grau de entrada 0 (zero), isto , um vrtice que no o ponto de chegada de nenhuma aresta. Imprimi-se esse vrtice, retira-se do grafo e o processo repetido at obteno de um conjunto vazio de vrtices. Eis o algoritmo: 7

procedimento Orden-Topo-Alt(G=(V,A): Grafo) Para j := 1 at n: Escolher um vrtice w de grau de entrada nulo Retirar w do grafo e todas as arestas ligas a w Imprimir(w) Utilizando esse algoritmo com o grafo ilustrado na figura 4, podemos obter a seguinte seqncia: C1, C2, C3, C4, C5, C6, C7, C8. Note que como a cada etapa do algoritmo pode existir mais de um vrtice de grau de entrada nulo, a resposta do algoritmo pode ser diferente. Veja por exemplo essa outra seqncia que ele poderia retornar: C1, C3, C5, C2, C7, C4, C6, C8. E muito fcil mostrar que o algoritmo funciona corretamente, pois a cada etapa selecionamos um vrtice que no tem nenhum predecessor, ou se ele tem, esse predecessor j foi processado anteriormente. Quanto ao tempo de execuo, ele depende da maneira de implementar o grafo. O ponto crtico a busca do vrtice de grau de entrada nulo (a remoo pode ser realizada em tempo constante). Se for usada uma matriz de adjacncia, o tempo para procurar um vrtice de grau de entrada nulo em O(n2). Como isso ser repetido n vezes, o tempo total em O(n3). Se for usada uma estrutura de adjacncia, a situao melhor se o grafo for esparso. A cada etapa o tempo para buscar o vrtice de grau nulo no mnimo n, pois todo elemento do vetor deve ser visitado para ver se ele foi eliminado. Alm disso, ser preciso visitar todas as arestas do grafo. Ento teremos um tempo de execuo em O(n+m) a cada iterao. No total, isso d um tempo em O(n2+ nm). Algoritmo 3 O algoritmo anterior menos eficiente que o primeiro, que O(n+m) = O(max(n,m)). Mas possvel transformar o algoritmo anterior de tal maneira que ele tenha a mesma complexidade. s utilizar um vetor G[1..n] que memoriza o grau de entrada de cada vrtice e uma lista L que contm todos os vrtices de grau de entrada nulo. procedimento Orden-Topo-Alt-Modif(G=(V,A): Grafo) L := {} Para i := 1 at n: G[i] := 0 Para i := 1 at n: Para cada vrtice j tal que existe uma aresta de i para j: G[j] := G[j] + 1 Para i := 1 at n: Se G[i] = 0: L := L U {i} Enquanto L no vazia v := um vrtice de L imprimir(v) L := L - {v} Para cada vrtice w tal que existe uma aresta de v para w: G[w] := G[w] - 1 Se G[w] = 0: L := L U {w} 8

No difcil de verificar que este algoritmo tem complexidade O(n+m). A sua anlise foi deixada como exerccio. Identificao de componentes fortemente conexos Um grafo direcionado fortemente conexo se existe um caminho de u at v e de v at u para qualquer par distinto de vrtices u e v. Se um grafo no fortemente conexo, podemos estar interessados em saber quais so os seus subgrafos que so fortemente conexos. Cada um desses subgrafos chamado componente fortemente conexo.

Figura 5 Considere o grafo ilustrado na figura 5. Podemos ver que ele contm trs componentes fortemente conexos: {1,2,3,4}, {6}, {5,8,9,10} e {7,11}. Existe uma maneira interessante de visualizar o grafo se consideramos cada componente como um vrtice. Isso uma representao de como ir de um componente a outro componente. Veja na figura 6 essa representao do grafo da figura 5.

Figura 6 Para identificar os componentes fortemente conexos de um grafo, preciso primeiro modificar a busca em profundidade, para obter uma numerao ps-ordem dos vrtices da rvore que resulta da busca. Para isso, so incrementar um contador no momento da sada de uma chamada recursiva. Supondo uma varivel global posnum[1..n] , eis o algoritmo modificado:

procedimento Busca(G: Grafo) nump := 0 Para Cada vrtice v de G: Marque v como no visitado Para Cada vrtice v de G: Se v no foi visitado: Busca-Prof(v) procedimento Busca-Prof(v: vrtice) Marque v como visitado Para Cada vrtice w adjacente a v: Se w no foi visitado: Busca-Prof(w) nump := nump + 1 posnum[v] := nump Agora, podemos apresentar o algoritmo que identifica os componentes fortemente conexos de um grafo G: Passo 1: Realizar uma busca em profundidade em G. Consideramos que depois dessa busca, cada valor posnum[v] representa a posio do vrtice v na sequncia resultando de percurso ps-ordem. Passo 2: Construir um grafo G' que igual a G, s que a orientao de cada aresta invertida. Passo 3: Realizar uma busca em profundidade em G', comeando com o vrtice que tem o maior valor em posnum.. Passo 4: Cada rvore da floresta que resulta da etapa precedente contm todos os vrtices de um componente fortemente conexo de G. Vamos ver agora a aplicao desse algoritmo ao exemplo da figura 5. Suponhamos que a busca em profundidade corresponde rvore ilustrada na figura 7. A figura 8 ilustra o grafo G'. Ao lado de cada vrtice indicado um valor que representa a posio desse vrtice no percurso ps-ordem da rvore obtida na busca em G.

10

Figura 7

Figura 8 Realizando a busca em profundidade no grafo G' ilustrado na figura 8, obtemos as rvores ilustradas na figura 9. Isso corresponde ao resultado esperado.

11

Figura 9 Para se convencer que o algoritmo funciona, devemos provar o seguinte: Teorema1: Dois vrtices u e v esto no mesmo componente fortemente conexo se e somente se eles aparecem na mesma rvore quando o algoritmo termina. Prova da ida: Suponhamos que u e v so no mesmo componente fortemente conexo. Isso implica que existe um caminho de u at v e vice versa. Se isso vale para G, vale para G' tambm. Na busca efetuada em G', um dos dois vrtices u e v ser visitado primeiro. Supondo que u seja esse vrtice. Como existe um caminho de u at v, necessessariamente esse ltimo estar na mesma rvore, considerando que a busca em profundidade visita de maneira exaustiva todos os vrtices alcanveis a partir do vrtice inicial. Prova da volta: Seja v um vrtice em uma rvore cuja raiz r quando realizamos a busca em G', e suponhamos vr. Isso implica que existe um caminho de r at v no grafo G', e portanto de v at r no grafo G. Como r foi selecionado primeiro, sabemos que posnum[r] >posnum[v] . Consideremos agora as posies possveis de r relativamente a v na rvore que corresponde busca em profundidade realizada em G. H trs possibilidades: 1. r ancestral de v. 2. r descendente de v. 3. r no nem ancestral nem descendente de v. Consideremos o segundo caso. Se r descendente de v, ele deveria ter o valor menor na ordenao ps-ordem. J sabemos que isso no o caso, pois posnum[r] > posnum[v] . Portanto, o segundo caso excluido. Suponhamos agora a terceira possibilidade. Como posnum[r] >posnum[v] , ento o vrtice r foi visitado depois de v e est direita de v na rvore. O caminho de v at r no pode ser como ilustrado na figura 9'a, onde no existe um vrtice que ancestral dos dois. Se tivesse tal caminho, r seria descendente de v na rvore de busca. Portanto, o caminho de v at r deve subir na rvore at um vrtice x que ancestral de v e r, como ilustrado na figura 9'b. Isso supe um vrtice x tal que posnum[x] >posnum[r] , o que impossvel. Isso porque no possvel que r seja selecionado antes de x para lanar a busca. Assim, r e v j seriam absorvidos na rvore de x e r no pode ser a raiz de v. Portanto, sobra somente a primeira possibilidade, que implica que existe um caminho de r at v.

12

Figura 9' Consideremos agora dois vrtices u e v da mesma rvore onde nenhum deles a raiz. Seja r a raiz dessa rvore. J provamos que existe um caminho que vai de cada um desses vrtices at a raiz, e da raiz at cada um desses vrtcies. Ento existe um caminho de u at v passando por r, e vice versa. 2. BUSCA EM LARGURA Em uma busca em largura a partir de um vrtice v, esperamos que todos os vizinhos de v sejam visitados antes de continuar a busca mais profundamente. Contrariamente busca em profundidade, o algoritmo de busca em largura no recursivo. Mas pode ser comparado verso iterativa da busca em profundidade, que usa uma pilha P: procedimento Busca-Prof-Iter(v: vrtice) Inicializar P Marcar v como visitado Empilhar v em P Enquanto P no vazio: Enquanto existe um vrtice w adjacente ao vrtice no topo de P: Marcar v como visitado Empilhar w em P Retirar o primeiro elemento de P O algoritmo de busca em largura semelhante ao algoritmo de busca em profundida. A principal diferena que usamos um fila F ao invs de uma filha:

13

procedimento Busca-Largura(v: vrtice) Inicializar F Marcar v como visitado Colocar v no final de F Enquanto F no vazio: u := primeiro elemento de F Retirar u de F Para cada vrtice w adjacente a u: Se w no foi visitado: Marcar w como visitado Colocar w no final de F Nos dois casos preciso um programa para lanar a busca: procedimento Busca(G: Grafo) Para cada vrtice v de G: Marcar v como no visitado Para cada vrtice v de G: Se v no foi visitado: {Busca-Largura ou Busca-Prof-iter}(v) Aplicando o algoritmo de busca em largura ao grafo da figura 2, poderiamos obter a rvore geradora ilustrada na figura 10:

Figura 10 muito fcil ver que o tempo de execuo da busca em largura o mesmo que o tempo de execuo da busca em profundidade: O(n+m), ou O(max(n,m)). Mas se consideramos a memria, o desempenho pior. Na busca em profundidade, somente um "ramo" da rvore empilhado a cada momento. Ento a pilha no conter mais de n elementos. Na busca em largura, como todos os filhos de um vrtice so empilhados a cada etapa, o espao ocupado em memria tende a ser exponencial. Um exemplo de aplicao da busca em largura a identificao do caminho mais curto entre dois vrtices. Nesse caso, o desempenho do algoritmo melhor que os algoritmos de Dijkstra e Floyd. Outra situao onde a busca em largura pode ser usada quando temos um grafo infinito. Nesse caso, a busca em profundidade pode entrar em um ramo sem sada.

14

3. EXERCCIOS Exerccio 1: Discuta o tempo de execuo do algoritmo de busca em profundidade se utilizamos uma matriz de adjacncia ao invs de uma estrutura de adjacncia. Exerccio 2: Utilize o algoritmo de busca em profundidade para identificar as componentes conexas de um grafo no direcionado. Exerccio 3: Escreva uma verso iterativa do algoritmo de busca em profundidade. Exerccio 4: Escreva em detalhe o algoritmo de busca de articulao e analise sua complexidade. Exerccio 5: Prove que, em um grafo G conexo, uma aresta que no aparece numa rvore de profundidade necessariamente liga um vrtice com um dos seus ancestrais na rvore. Exerccio 6: Prove que um vrtice v em um grafo conexo uma articulao se e somente se existe dois vrtices m e b diferentes de v tais que todo caminho entre m e b passa por v. Exerccio 7: Prove que, em um grafo G direcionado, se (v,w) uma aresta que no aparece na rvore resultante de uma busca em profundidade, e se v no nem ancestral nem descendente de w, ento prenum[v]> prenum[w]. Exerccio 8: Mostre como a remoo de um vrtice de grau de entrada nulo pode ser implementado em tempo constante no algoritmo Orden-Topo-Alt. Responda para os dois casos: utilizao de estrutura de adjacncia e utilizao de matriz de adjacncia. Exerccio 9: Mostre que o algoritmo Orden-Topo-Alt-Modif apresenta um tempo de execuo em O(m+n). Exerccio 10: Qual o tempo de execuo do algoritmo para identificao de componentes fortemente conexos?

Figura 11 Exerccio 11: Considere os grafos da figura 11. Qual a ordem de visita dos vrtices em uma busca em profundidade, comeando pelo vrtice m. Responda mesma pergunta com os outros vrtices. Exerccio 12: Considere os grafos da figura 11. Qual a ordem de visita dos vrtices em uma busca em largura, comeando pelo vrtice m. Responda mesma pergunta com os outros vrtices. Exerccio 13: Aplique o algoritmo de identificao de componentes fortemente conexos no grafo 11b. 15

Figura 12 Exerccio 14: Aplique o algoritmo de identificao de articulaes nos grafos da figura 12. Exerccio 15: Escreva um algoritmo em O(n+m) para determinar se um grafo no direcionado de n vrtices contm circuitos. Exerccio 16: Escreva um algoritmo para determinar se possvel colorir todos os vrtices de um grafo, usando somente duas cores e de tal maneira que nenhum vrtice tenha a mesma cor que qualquer de seus vrtices adjacentes. Exerccio 17: Modifique o algoritmo de busca em profundidade para que ele seja capaz de identificar se um grafo conexo. Exerccio 18: Dado um grafo orientado, faa um algoritmo de complexidade O(n+m) capaz de inverter as direes das arestas do grafo e quais seus componentes conexos. Exerccio 18: Dado um grafo, faa um algoritmo de complexidade O(n+m) capaz de verificar e se o grafo bipartite e identificar as suas parties.

16

Potrebbero piacerti anche