Docsity
Docsity

Prepare-se para as provas
Prepare-se para as provas

Estude fácil! Tem muito documento disponível na Docsity


Ganhe pontos para baixar
Ganhe pontos para baixar

Ganhe pontos ajudando outros esrudantes ou compre um plano Premium


Guias e Dicas
Guias e Dicas


Lista Exercicio Grafos, Exercícios de Computação Aplicada

Lista de exercícios sobre grafos. Respostas de exercícios.

Tipologia: Exercícios

2020

Compartilhado em 01/07/2020

francisco-santos-czi
francisco-santos-czi 🇧🇷

1 documento

1 / 21

Toggle sidebar

Esta página não é visível na pré-visualização

Não perca as partes importantes!

bg1
1.a. Não existe grafo não-dirigido, pois o número de vértices de grau ímpar de um
Grafo G qualquer, não-dirigido, é sempre par.
Existem 7 vértices de grau ímpar(1, 1, 3, 3, 3, 7, 9)
1.b. Não seria possível, pois num momento qualquer de uma festa qualquer,
sempre vão existir duas pessoas que apertaram o mesmo número de mãos. Seja n
o número de pessoas na festa. Uma pessoa pode apertar, no máximo, n 1 mãos
e, no mínimo, nenhuma. Se num dado momento houver k indivíduos que ainda não
cumprimentaram ninguém, o número máximo de apertos de mão que alguém pode
ter dado será n k 1. Excetuando esses indivíduos que não cumprimentaram
ninguém, sobram nk pessoas, que terão que ser distribuídas entre os n k 1
números possíveis de apertos de mão 1, 2, · · · , n k 1. Pelo Princípio da Casa
de Pombos, duas delas terão dado o mesmo número de apertos de mão. Note que
podemos tomar k = 0, obtendo o mesmo resultado.
1.c. Os grafos não são isomorfos. Não compartilham a mesma matriz de
adjacência.
VERIFICAR A SEQUENCIA DE GRAUS DOS VIZINHOS
2.a Um emparelhamento 𝑀 é um conjunto de arestas com a propriedade de que
todo vértice de 𝐺 incide em no máximo uma aresta de 𝑀. Um emparelhamento é
perfeito quando todo vértice de 𝐺 incide em exatamente uma aresta de 𝑀. O
emparelhamento perfeito contêm no máximo |𝑉 (𝐺)|/2 arestas e também pode-se
dizer que emparelhamentos perfeitos são possíveis quando o grafo possui
número par de vértices.
2.b Um caminho M-alternante P para um emparelhamento M é aquele onde as
arestas se alternam entre arestas que pertencem a M e arestas que não
pertencem a M, isto é, é um caminho tal que as arestas de P estão alternadamente
em A\ M e M . Ex e mpl o : A lt e r na n te { (D, H ), ( F, B) } e A um e nt a n te
{A(A,B),C(C,F),D(D,G),H(H,E)}
Caminho M-aumentante ou caminho de aumento é um caminho M-alternante onde
os extremos (vértices final e inicial) não são saturados pelas arestas de M.
Sempre que existir um caminho M-aumentante, o emparelhamento M não será
máximo em G, ou seja, haverá um emparelhamento M’ máximo tal que M M’.
O contrário também é verdadeiro, resultado do Teorema de Berge.
pf3
pf4
pf5
pf8
pf9
pfa
pfd
pfe
pff
pf12
pf13
pf14
pf15

Pré-visualização parcial do texto

Baixe Lista Exercicio Grafos e outras Exercícios em PDF para Computação Aplicada, somente na Docsity!

1.a. Não existe grafo não-dirigido, pois o número de vértices de grau ímpar de um Grafo G qualquer, não-dirigido, é sempre par. Existem 7 vértices de grau ímpar(1, 1, 3, 3, 3, 7, 9) 1.b. Não seria possível, pois num momento qualquer de uma festa qualquer, sempre vão existir duas pessoas que apertaram o mesmo número de mãos. Seja n o número de pessoas na festa. Uma pessoa pode apertar, no máximo, n − 1 mãos e, no mínimo, nenhuma. Se num dado momento houver k indivíduos que ainda não cumprimentaram ninguém, o número máximo de apertos de mão que alguém pode ter dado será n − k − 1. Excetuando esses indivíduos que não cumprimentaram ninguém, sobram n−k pessoas, que terão que ser distribuídas entre os n − k − 1 números possíveis de apertos de mão 1, 2, · · · , n − k − 1. Pelo Princípio da Casa de Pombos, duas delas terão dado o mesmo número de apertos de mão. Note que podemos tomar k = 0, obtendo o mesmo resultado. 1.c. Os grafos não são isomorfos. Não compartilham a mesma matriz de adjacência. VERIFICAR A SEQUENCIA DE GRAUS DOS VIZINHOS 2.a Um emparelhamento 𝑀 é um conjunto de arestas com a propriedade de que todo vértice de 𝐺 incide em no máximo uma aresta de 𝑀. Um emparelhamento é perfeito quando todo vértice de 𝐺 incide em exatamente uma aresta de 𝑀. O emparelhamento perfeito contêm no máximo |𝑉 (𝐺)|/2 arestas e também pode-se dizer que emparelhamentos perfeitos só são possíveis quando o grafo possui número par de vértices. 2.b Um caminho M-alternante P para um emparelhamento M é aquele onde as arestas se alternam entre arestas que pertencem a M e arestas que não pertencem a M, isto é, é um caminho tal que as arestas de P estão alternadamente e m A \ M e M. E x e m p l o : A l t e r n a n t e { ( D , H ) , ( F, B ) } e A u m e n t a n t e {A(A,B),C(C,F),D(D,G),H(H,E)} Caminho M-aumentante ou caminho de aumento é um caminho M-alternante onde os extremos (vértices final e inicial) não são saturados pelas arestas de M. Sempre que existir um caminho M-aumentante, o emparelhamento M não será máximo em G, ou seja, haverá um emparelhamento M’ máximo tal que M ⊂ M’. O contrário também é verdadeiro, resultado do Teorema de Berge.

No Grafo em questão, o emparelhamento não é máximo, pois existe um caminho M-aumentante. O Teorema de Berge diz que dado um grafo G e um emparelhamento M em G, M é um emparelhamento máximo se e somente se G não tem nenhum caminho M- aumentante em relação a M. No grado em questão, existe um caminho M’ tal que M ⊂ M’, {D(D,A),B(B,C),F(F,J),H(H,G)}, de forma que M nã é máximo.

  1. Verifica se existe vértices livres para aumentar o caminho. Um caminho de aumento começa e termina em um vértice livre e arestas alternadas.
  2. Começando em A como nó raiz.
  3. Execute o BFS(Breadth-First Search) até alcançar outro vértice. Colore o nó atual com vermelho e explora os vizinhos desse nó. Visita o próximo vizinho(B) e o colore de amarelo, caso ainda não tenha sido emparelhado. Se econtrou um caminho aumentante, pinta as arestas de verde(A,B), caso contrário não existe mais vértices não emparelhados e termina o algoritmo.
  4. Se ainda existem vértices não emparelhados, (C,D,E,F,G,H,J). Pega um vértice livre, C, repete o passo 3 e encontra o emparelhamento (C,F).
  5. Se ainda existem vértices não emparelhados, (D,E,G,H,J). Pega um vértice livre, D, repete o passo 3 e encontra o emparelhamento (D,G).
  6. Se ainda existem vértices não emparelhados, (E,H,J). Pega um vértice livre, E, repete o passo 3 e encontra o emparelhamento (E,H).
  7. Se ainda existem vértices não emparelhados, (J). Pega um vértice livre, D, repete o passo 3.

A partir da lista de adjacência, iniciamos pela primeira variável, que é por sua vez o primeiro vértice do grafo.

  1. Atribuímos uma cor a esse vértice(p) e a todos os outros na sequência, a que ele é adjacente(q). Terminado sua lista de adjacência, partimos para o próximo vértice, que no caso será o (q).
  2. Partindo agora da lista de (q) atribuímos cores aos seus vértices adjacentes, diferentes da cor atribuída a (q). Percebe-se nessa situação que se o número de cores for menor ou igual a 3 fica impossível colorir os vértices. Logo necessitamos de pelo menos 4 cores. Terminado sua lista de adjacência, partimos para o próximo vértice, que no caso será o (r), uma vez que o (p) já foi visitado.
  3. Partindo agora de (r) executa-se os mesmos passos das sequências anteriores, observando os vértices que já foram visitados, e que portanto já possuem cores associadas (p, q, u, v). Os vértices (w, x, y) serão coloridos. Para isso, necessitamos de apenas duas ou três cores.
  4. Segue-se para o próximo vértice ainda não visitado, que no caso é o (z) terminando o processo. O número mínimo de registradores utilizados é igual a 4. Reg1.: p, r, z Reg2.: q, w, y Reg3.: u, x Reg4.: v

O grafo representa a lista de conhecidos de Zezinho. Cada vértice representa um conhecido e as arestas representam as relações de amizade entre eles. Cada hexágono representa seis pessoas, onde cada pessoa do hexágono conhece outras cinco. Cada grupo(hexágono) compartilha pelo menos uma pessoa conhecida com outro grupo e cinco que não são conhecidas. O grafo será representado por um matriz de adjacências, em que se o convidado i conhecer o convidado j, na matriz de adjacências, o elemento (i,j) terá o valor 1 indicando que os indivíduos se conhecem e 0(zero) caso contrário. O algoritmo recebe como entrada a matriz de adjacências, Mat. Algoritmo(Mat: matriz de adjacências) conhecidos = 0 estranhos = 0 para i variando de 0 até linhas(Mat) faça para j variando de 0 até colunas(Mat) faça se Mat[i,j]=1 faça conhecidos = conhecidos + 1 senão faça se j diferente de i faça estranhos = estranhos + 1 se conhecidos>=5 e resto_divisao(conhecidos,5)=0 e estranhos>= faça

5.b

O problema pode ser resolvido com a utilização do algoritmo de Dijkstra. Dada a matriz de adjacência do grafo, o algoritmo de Dijkstra retorna uma árvore com o caminho mínimo do vértice origem (s) ao destino, no caso da questão, de P1 a P6. O caminho mínimo representa o tempo de troca dos programas. Pseudo-código Enquanto True faça caminho <- Dijkstra(G, s) caminho <- sort(caminho) # ordena a lista retornada pelo algoritmo dijkstra para p em caminho faça execute p Retorno do Algoritmo Prog. 0 3 5 1 4 2 Dist 0 10 10 30 30 40 Segue um passo-a-passo da execução do algoritmo

6.b G: grafo representado como lista de adjacência cost : matriz de distâncias entre os vértices Algoritmo DFS(G, cost, origem, destino) custo[origem] <- 0 visitado : lista vazia path: lista vazia fullpath: lista vazia contapath = 0 retorne VISITA_DFS(origem, destino, path, fullpath, visitado, cost, custototal=0, contapath) Algoritmo VISITA_DFS(origem, destino, visitado, path, fullpath, visitado, cost, custototal, contapath) visitado.push(origem) path.push(origem) se origem==destino faça contapath = contapath + 1 fullpath.push(path) custo = 0 para i em range((tamanho de path)-1) faça custo = custo + cost[path[i]][path[i+1]] custototal.push(custo) para cada v em Adj(G[origem]) faça se v não está em visitado faça VISITA_DFS(v, destino, path, fullpath, visitado, cost, custototal, contapath) path.pop() visitado.pop() se path é vazio faça retorne fullpath do min(custototal) origem = 0 # vértice de origem, no caso, Zezinho retorno = lista vazia # lista qye retorna os ca minhos mínimos de Zezinho a todos os outros vértices para i=origem aré Nr.Vértices-1 faça: amigos = DFS(G, cost, origem, i+1)

retorno.push(amigos) pares: lista vazia #armazena os amigos distantes da rede de amigos de Zezinho para path em retorno faça: if tamanho(path)>2 faça pares.push(ultimo elemento de path) para i=0 até tamanho(pares)-1 faça para j =i+1 até tamanho(pares) faça left = DFS(G, cost, origem, pares[i]) # retorna um vértice distante de Zezinho, aqui nomeado de left (relativo a i) right = DFS(G, cost, origem, pares[j]) # retorna um vértice distante de Zezinho, aqui nomeado de right (relativo a j) se tamanho(left)==tamanho(right) faça left.pop() right.pop() se left!=right faça Imprima ‘Par (pares[i], pares[j]) atende aos requisitos senão faça Imprima ‘Não existe par que atenda aos requisitos’ Código Python com exemplo import sys import numpy as np custo = [0]* def dfs(gr, cost, origem, destino): custo[origem]= return visita_dfs(origem, destino, [], [], [], cost, [], 0)

DFS algorithm

def visita_dfs(origem, destino, path, fullpath, visitado, cost, custoTotal, contapath): visitado.append(origem) path.append(origem) if origem==destino: contapath+= fullpath.append(list(path)) custo = 0 for i in range(len(path)-1):

for path in retorno: if len(path)>2: pares.append(path[-1]) for i in range(len(pares)-1): for j in range(i+1,len(pares)): left = dfs(gr, cost, origem, pares[i]) right = dfs(gr, cost, origem, pares[j]) if len(left)==len(right): left.pop() right.pop() if left!=right: print('Par:(%s,%s) atende aos requisitos'%(pares[i], pares[j])) else: print('Não existe par que atenda aos requisitos') 7.a O algoritmo de Kosaraju baseia-se na definição de que um Grafo G e o seu transposto T(G) possuem exatamente os mesmos componentes fortemente conectados. Se aplicar a alteração proposta por Zezinho, o algoritmo não funcionará corretamente. A segunda busca vai executar os mesmos passos da primeira busca e não vai identifica os componentes fortemente conectados. Considere o grafo abaixo como exemplo. Passos do Kruskal original Primeiro DFS Visita(0): 0 1 2 3 Pilha(0): 3 Visita(1): 4 5 6 7 Pilha(1): 7 Visita: 0 1 2 3 4 5 6 7 Pilha: 3 7 Como 6 5 4 3 2 1 e 0 já foram visitados, empilha-os Pilha: 3 7 6 5 4 2 1 0

Segundo DFS Inverte o grafo Começa no topo da pilha. Atravessa todos os filhos do vértice. Se o vértice já tiver sido visitado, um componente fortemente conectado foi alcançado. Pilha: 3 7 6 5 4 2 1 0 Começando do 0 , visita os vértices 1 2 e 3 em sequência. Como o filho do vértice 3 já foi visitado, alcançou um componente fortemente conectado. Visita(0): 0 1 2 3 Pilha(0): 3 7 6 5 4 2 1 SCC(0) 0 1 2 3 Vai ao topo da pilha e retira os vértices já visitados Escolhe o topo da pilha(4) o retira da pilha e visita todos os filhos(5 e 6). Pilha(1): 3 7 6 5 Visita(1): 0 1 2 3 4 5 6 SCC: 4 5 6 Ao encontrar um vértice já visitado, alcançou um componente fortemente conectado (4 5 6). Vai ao topo da pilha e retira os vértices já visitados Pilha(2): 3 7 Visita o topo da pilha (7) e o retira da pilha. Visita os filhos do vértice. No caso, não tem mais filhos, retorna um componente fortemente conectado. SCC: 7 Vai ao topo da pilha e retira os vértices já visitados. A pilha fica vazia. Pilha: [] Passos do Kruskal sugerido por Zezinho Primeiro DFS Visita(0): 0 1 2 3 Pilha(0): 3 Visita(1): 4 5 6 7 Pilha(1): 7 Visita: 0 1 2 3 4 5 6 7 Pilha: 3 7 Como 6 5 4 3 2 1 e 0 já foram visitados, empilha-os

8.b Sim, é possível. Kruskal

  1. Ordena as arestas do grafo em ordem crescente pelo peso das arestas;
  2. Pega a aresta com o meno peso e a adicionar á árvore. Se o ciclo for criado, descarta a aresta
  3. Continua adicionando arestas(Passo 1) até que todos os vértices sejam considerados. Prim
  4. Escolhe um vértice aleatório e inicializa a árvore;
  5. Encontra as arestas que o conectam a outros vértices. Seleciona a aresta com o meno peso e adiciona o vértice à árvore;
  6. Repete o passo 2 até que a árvore esteja formada. Como o algoritmo de Kruskal faz uma ordenção das arestas pelos seus pesos em ordem crescente pode ocorrer de uma aresta da solução parcial em Kruskal seja inserida na ordem inversa da obtida no algoritmo de Prim, uma vez que o algoritmo de Prim vai adicionando as arestas na ordem em que aparecem. Exemplo 8.b. Kruskal Considerando o grafo 8.b, o algoritmo de Kruskal faz a ordenção das arestas, obtendo { [2,4,1],[2,3,2],[0,1,3],[0,3,3],[1,4,4] } Sua execução passo a passo resulta nas seguintes arestas: 2-4, 2-3, 0-1, 0- Prim Considere que o algoritmo de Prim começa no vértice 2
  7. Seleciona a aresta que possui o menor peso a partir de 2. No caso, 4 (2,4)
  8. Seleciona a próxima aresta com o menor peso a partir de 2. No caso, 3 (2,3)
  9. Seleciona a próxima aresta com menor peso a partir de 3. No caso, 0 (3,0). Veja que aqui já inverteu a ordem da mesma aresta retornada por Kruskal.
  10. Seleciona a próxima aresta com menor peso a partir de 0. No caso, 1 (0,1).

9.a cost : matriz de distâncias entre os vértices Algoritmo DFS(G, cost, origem, destino) custo[origem] <- 0 visitado : lista vazia path: lista vazia fullpath: lista vazia imprime VISITA_DFS(origem, destino, path, fullpath, visitado, cost, custototal) Algoritmo VISITA_DFS(origem, destino, visitado, path, fullpath, visitado, cost, custototal) visitado.push(origem) path.push(origem) se origem==destino faça fullpath.push(path) custo = 0 para i em range((tamanho de path)-1) faça custo = custo + cost[path[i]][path[i+1]] custototal.push(custo) para cada v em Adj(G[origem]) faça se v não está em visitado faça VISITA_DFS(v, destino, path, fullpath, visitado, cost, custototal) path.pop() visitado.pop() se path é vazio faça retorne fullpath do max(custototal), max(custototal) origem= Para i=origem até Nr.Vértices-1 faça imprima ‘Origem:’, origem, ‘->Destino:’, i+ DFS(G, cost, origem, i+ 1 ) Código Python Exemplo import sys

9.b O algoritmo proposto não funcionará corretamente, pois o algoritmo de. Bellman-Ford assume que não existe ciclo negativo. Ao se efetuar a alteração proposta pode ocorrer ciclo negativo o que invalida a execução do algoritmo. 9.c Algoritmo FloydWarshall ( G ) Entrada digrafo ponderado G = ( V , E ) Saída matriz de distâncias D i1 para cada vV faça rotule v como vi ii + 1 D^0 ← W para k1 até n faça para i1 até n faça para j1 até n faça

Dk [ i ][ j ]min{ Dk -1[ i ][ j ], Dk -1[ i ][ k ] + Dk -1[ k ][ j **]} #### - Linha original do

algoritmo comentada

Linhas acrescentadas para detectar ciclo negativo

se** Dk -1[ i ][ k ] + Dk -1[ k] [ j ] < Dk -1[ i ][ j ] então Dk -1[ i ][ j ] = Dk -1[ i ][ k ] + Dk -1[ k ][ j ] para i ← 1 até n faça se ( D^0 [i][i] < 0) então return True return False Se retornar True é porque existe ciclo negativo

Para encontrar o fluxo máximo, usa-se o algoritmo de Ford-Fulkerson Algoritmo FordFulkerson ( N ) Entrada: rede de fluxo N = ( G , c , s , t ), onde G = ( V , E ) Saída: um fluxo máximo f para N para cada ( u , v )E faça f [ u , v ]0 //guarda o valor do fluxo do arco de u a v continuaVERDADEIRO enquanto ( continua ) faça //laço principal π ← CAM_AUM_DFS( N , f ) //busca via DFS um caminho de aumento se ( π != NIL) //existe um caminho de aumento na rede residual ∆ ← ∞ para cada ( u , v ) ∈ π faça se (f( u , v ) <) ∆ ← ∆ f( u , v ) //computa a capacidade residual do caminho //atualiza o valor da capacidade residual //adiciona o fluxo residual aos arcos do caminho //retorna verdadeiro se o arco for de avanço para cada ( u , v ) ∈ π faça se (ARCO_AVANCO( u , v )) f [ u , v ]f [ u , v ] +senão f [ u , v ]f [ u , v ] -senão continuaFALSO retorna f A seguir, executamos o passo-a-passo do algoritmo de Ford-Fulkerson para resolver o problema do fluxo máximo da questão 10. O conjunto de bondes críticos é b-c-a-d