BCC402 Algoritmos e Programação Avançada · 2012-03-12 · BCC402 Algoritmos e Programação...
Transcript of BCC402 Algoritmos e Programação Avançada · 2012-03-12 · BCC402 Algoritmos e Programação...
BCC402 Algoritmos e Programação Avançada Prof. Marco Antonio M. Carvalho Prof. Túlio Toffolo 2012/1
¡ Definições e Estruturas de Grafos ¡ Representações; ¡ Percursos
§ Busca em Largura; § Busca em Profundidade.
¡ Aplicações; ¡ Grafos Especiais; ¡ Códigos.
¡ Veremos estruturas e algoritmos relacionados a grafos § Os códigos serão fornecidos.
¡ No entanto, somente conhecer as estruturas e algoritmos não são suficientes § É necessário praticar a utilização dos mesmos; § Conhecer minimamente a implementação também é desejável.
¡ Teoria dos grafos no ICPC § Mínimo de 1 problema; § Normalmente 2; § Máximo de 3.
¡ É necessário dominar as soluções para os problemas clássicos § Pequenas variações com programação dinâmica e algoritmos gulosos.
¡ Fazem toda a diferença em uma competição § Resolver 3 problemas podem colocar o time no top 10.
¡ Grafos são estruturas de dados muito importantes e recorrentes § Representam arbitrárias relações entre elementos.
¡ O primeiro registro de uso data de 1736, por Euler § O problema era encontrar um caminho circular por Königsberg (atual Kaliningrado) usando cada uma das pontes sobre o rio Pregel (ou Pregolya, Pregola) exatamente uma vez.
1
3
24
• Infelizmente (?), este problema não tem solução; • Por outro lado, a teoria de grafos foi desenvolvida.
¡ Grafos podem ser utilizados para modelar: § Malhas viárias; § Dutos (oleodutos, gasodutos, etc.); § Circuitos eletrônicos; § Redes (elétricas, de computadores, etc.); § Programas; § Interações humanas; § Enfim, inúmeras situações.
¡ Um grafo G é um par G=(V, E) consistindo de um conjunto não vazio V e um conjunto E de pares de elementos contidos em V § Os elementos de V são os vértices ou nós; § Os elementos de E são as arestas entre vértices, e podem ter
pesos, ou valores associados.
1
3
24
Vértice
Aresta
¡ Se existe uma aresta e entre os vértices u e v § Usamos a notação e = (u, v); § Os vértices são ditos vizinhos ou adjacentes; § A aresta e é dita incidente a u e v;
¡ O grau de um vértice u, denotado por d(u), é o número de arestas incidentes a u.
¡ Se em e =(u, v), u e v são o mesmo vértice, a aresta e é um laço ou loop;
¡ Em alguns casos, entre o mesmo par de vértices pode haver mais de uma aresta. Neste caso, elas são paralelas ou múltiplas.
1
2
3
1
2 3
4
¡ Um grafo sem arestas múltiplas, ou loops é dito simples;
¡ Um grafo com este tipo de arestas é dito não simples § Pode ser utilizado para representar situações em que dois elementos são ligados por mais que um meio ▪ Diferentes estradas entre duas cidades; ▪ Ou diferentes dutos entre dois pontos.
¡ Algoritmos diferenciados para percurso em cada um dos tipos de grafos.
¡ Em um grafo orientado, ou dígrafo, as arestas possuem uma orientação definida § O termo arco também é utilizado para se referir a este tipo de aresta;
§ Ao invés de denotarmos e=(u, v), denotamos e=uv indicando os vértices inicial e final;
1
2 3
45
¡ Grafos direcionados podem ser utilizados para modelar ruas de cidades, pois (geralmente) são de mão única;
¡ Em um grafo não orientado, as arestas podem ser consideradas em qualquer direção § Por exemplo, modelam estradas, que usualmente são de mão dupla;
¡ Grafos nos quais as arestas possuem valores ou pesos são chamados grafos ponderados § Representam situações em que haja distância, tempo, fluxo ou
capacidade.
Ouro Preto
Belo Horizonte
115
Mariana
18
Congonhas55
6892
157
¡ A noção de valores em arestas introduz o conceito de menor caminho entre vértices § Para grafos não ponderados, o menor caminho é aquele com menos arestas, uma vez que todas têm o mesmo peso (considerado unitário);
§ Para grafos ponderados, algoritmos mais elaborados são necessários, uma vez que há diversas combinações de arestas com pesos diferentes.
¡ Um caminho em um grafo é uma sequência de vértices conectados entre si, formando um percurso em um grafo. § O caminho é delimitado por um vértice inicial e um vértice final; § Em um caminho simples, cada vértice aparece uma única vez; § O comprimento de um caminho é a sua quantidade de vértices.
1
2 3
4
5
• Este exemplo de caminho é denotado por 1→2→4→3→5
Vértice Inicial
Vértice Final
¡ Um ciclo ou circuito é um caminho em que o vértice inicial também é o vértice final § A escolha do vértice inicial é arbitrária. § Um grafo com ciclos é chamado cíclico;
1
2 3
4
5
• Este exemplo de ciclo pode ser denotado por 1→2→4→3→5→1.
¡ Duas formas padrão § Matriz de adjacências ▪ Indicada para grafos com muitas arestas.
§ Lista de adjacências ▪ Indicada para grafos com poucas arestas.
¡ Consiste em uma matriz |V|×|V| em que a posição i representa o vértice i;
¡ Caso exista uma adjacência entre os vértices i e j a posição i,j na matriz tem o valor 1, caso contrário tem o valor 0 § Em grafos orientados, apenas as arestas de saída são representadas;
§ No caso de grafos ponderados, o valor 1 pode ser substituído pelo peso da aresta.
1
4 5
3
2
1
4 5
3
2
1 2 3 4 5 1 0 1 0 1 0 2 1 0 1 1 1 3 0 1 0 0 1 4 1 1 0 0 1 5 0 1 1 1 0
1 2 3 4 5 1 0 1 0 1 0 2 0 0 1 0 1 3 0 0 0 0 1 4 0 1 0 0 0 5 0 0 0 1 0
¡ Consiste em um vetor de |V| listas. Em cada posição i, há uma lista onde cada elemento é um vértice adjacente ao vértice i; § No caso de grafos não orientados, as adjacências são armazenadas em ambos os vértices de incidência;
§ Em grafos dirigidos, apenas as arestas de saída são armazenadas.
§ Em casos de grafos ponderados, pode ser criado um campo em cada elemento da lista para armazenar o valor.
1
4 5
3
2
1
4 5
3
2
1 2 3 4 5
1
2
3
4
5
2 4 NULL
3 5 NULL
5 NULL
2 NULL
4 NULL
2 4 NULL
1 5 3 4 NULL
2 5 NULL
2 5 1 NULL
4 3 2 NULL
¡ O maior problema das listas de adjacências é determinar a existência de uma aresta § Na verdade, gerenciar as listas é uma complicação, mesmo para grafos pequenos.
¡ O ideal seria utilizar uma estrutura de fila e uma tabela hash para mapear as adjacências… § queue e map da STL!
¡ Está disponibilizado um conjunto de códigos originais do Skiena § Nome de funções, variáveis e comentários traduzidos; § Utilizam a estrutura de lista de adjacências em matrizes; § Os algoritmos a seguir também estão implementados.
¡ No entanto, é necessário saber o funcionamento dos algoritmos e também adaptar os códigos às necessidades § O uso dos códigos é opcional.
¡ A operação básica em grafos é o percurso § Ou seja, visitar todos os vértices e arestas uma única vez em alguma ordem;
¡ Uma possível dificuldade seria não terminar a busca nunca, por causa de repetição § Por isso marcamos os vértices já visitados.
¡ Existem dois algoritmos básicos § Busca em Largura; § Busca em Profundidade.
¡ Sem familiaridade com a busca em largura, alguns problemas podem parecer mais difíceis § 336 (a node too far) ▪ 383, 439, 532, 762, 10009.
¡ A busca em largura (Breadth-‐First Search -‐ BFS) expande a exploração de um grafo em níveis § A partir do vértice inicial, o nível explorado é o dos vértices adjacentes;
§ Após a exploração deste nível, passa-‐se à exploração do vértices adjacentes aos do nível anterior;
§ O procedimento se repete até que todos os vértices tenham sido explorados.
¡ Uma estrutura de fila é utilizada para guiar os passos da busca;
¡ Durante a exploração, um vértice é descoberto na primeira vez em que é encontrado, quando é então enfileirado § Representado pela cor cinza.
¡ Quando o vértice é retirado da fila, ele é considerado visitado § Todas as arestas incidentes a ele foram exploradas; § Representado pela cor preta.
2
6
1
4
8
5 97 3
• F: null
2
6
1
4
8
5 97 3
• F: 1→null
2
6
1
4
8
5 97 3
• F: 2→3→4→5→null
2
6
1
4
8
5 97 3
• F: 3→4→5→null
2
6
1
4
8
5 97 3
• F: 3→4→5→6→null
2
6
1
4
8
5 97 3
• F: 4→5→6→7→null
2
6
1
4
8
5 97 3
• F: 5→6→7→8→null
2
6
1
4
8
5 97 3
• F: 6→7→8→9→null
2
6
1
4
8
5 97 3
• F: 7→8→9→null
2
6
1
4
8
5 97 3
• F: 8→9→null
2
6
1
4
8
5 97 3
• F: 9→null
2
6
1
4
8
5 97 3
• F: null
¡ Sem familiaridade com a busca em profundidade e variantes, alguns problemas podem parecer mais difíceis § 469 (wetlands of florida) ▪ 260, 352, 572, 782, 784, 785.
§ 11504 (dominos) ▪ 1263 e 11709.
¡ A busca em profundidade (Depth-‐First Search -‐ DFS) explora todos os níveis de cada adjacência, uma por vez § A partir do vértice inicial, explora-‐se todos os níveis possíveis de uma adjacência;
§ Quando não for mais possível expandir a busca, retorna-‐se ao último nó com adjacências ainda não exploradas e retoma-‐se o processo;
§ A exploração é repetida até que todos os nós tenham sido visitados.
¡ Uma estrutura de pilha é utilizada para guiar os passos da busca;
¡ Durante a exploração, um vértice é descoberto na primeira vez em que é encontrado, quando é então empilhado § Representado pela cor cinza.
¡ Quando o vértice não possui mais adjacências a serem exploradas, ele é desempilhado, sendo considerado visitado ou terminado § Representado pela cor preta.
• P: null
2
6
1
4
8
5 97 3
• P: 1→null
2
6
1
4
8
5 97 3
• P: 2→1→null
2
6
1
4
8
5 97 3
• P: 6→2→1→null
2
6
1
4
8
5 97 3
• P: 2→1→null
2
6
1
4
8
5 97 3
• P: 1→null
2
6
1
4
8
5 97 3
• P: 9→5→1→null
2
6
1
4
8
5 97 3
• P: 8→4→1→null
2
6
1
4
8
5 97 3
• P: 7→3→1→null
2
6
1
4
8
5 97 3
• P: 1→null
2
6
1
4
8
5 97 3
2
6
1
4
8
5 97 3
• P: null
¡ Dois vértices u e v de um grafo G são ditos conexos se houver um caminho em G com início em u e final em v § Consideramos que todo vértice é conectado a si mesmo (mesmo sem a existência de uma aresta).
¡ Um Componente Conexo é formado por um conjunto de vértices conexos.
1
2 3
4 1
2 3
4
Um grafo conexo (ou conectado). Um grafo desconexo (ou desconectado).
O vértice 4 é isolado.
¡ Podemos usar tanto BFS quando DFS para detectar componentes conectados § Durante a exploração: ▪ Se todos os vértices foram visitados sem interrupções, o grafo é composto de um único componente conectado; ▪ Caso contrário, recomeçamos a exploração no primeiro vértice ainda não descoberto, detectando assim um novo componente conectado.
1
23
4
6 5
7
8
1
23
4
6 5
7
8
1
23
4
6 5
7
8
¡ Problema Clássico em Teoria de Grafos § Encontrar o menor caminho entre um vértice de origem e todos os demais;
§ Problema 336 Uva. ¡ Dados:
§ Um grafo não ponderado e não direcionado; § Um vértice inicial (V); § Um limite (L).
¡ Objetivo § Determinar quantos vértices estão a uma distância acima de L a partir de V;
§ Ou também, quantos vértices são inalcançáveis.
¡ Como o grafo não é ponderado, podemos considerar um custo unitário em cada aresta § Ou seja, o caminho de um vértice até outro é medido em quantidade de arestas percorridas.
¡ Podemos usar BFS para determinar este menor caminho § A cada nível explorado, o caminho é incrementado em um.
¡ Mas e se o grafo for ponderado? § Utilizamos o algoritmo de Dijkstra; § Assunto para outra aula…
¡ Flood Fill (ou Preenchimento de Regiões, Preenchimento de Polígonos), é uma operação fundamental em processamento de imagens § Consiste em preencher (fill) uma região de pixels (ou células em uma grade) adjacentes, desta forma, “inundando” (flooding) um polígono;
§ Como a ferramenta “Preencher com Cor” do Paint.
¡ Para nossos propósitos, usamos uma versão simplificada e menos formal: 1. A partir de uma célula inicial
1. Faça uma varredura e preencha as células adjacentes; 2. Evite preencher duas vezes uma mesma célula; 3. Observe a borda do polígono; 4. Termine quando todas as células adjacentes forem
preenchidas.
¡ Um algoritmo Flood Fill pode considerar apenas 4 adjacências por célula;
• Ou 8 adjacências por célula.
¡ A ordem em que a varredura é feita pode ser guiada por uma estrutura de fila ou pilha:
Fila Pilha
¡ Qual a relação do Flood Fill com percurso em grafos? § Embora não haja uma estrutura explícita de grafo, há um caso especial de grafo simples, não orientado, não ponderado em que existe um limite para o grau de cada nó;
§ A forma em que as adjacências são apresentadas (células de fato adjacentes em uma grade, ou matriz), dispensa a construção de outra estrutura;
§ A varredura para o preenchimento é um percurso em grafo, usando as mesmas estruturas.
¡ Alguns problemas clássicos são notoriamente difíceis § Não faria sentido colocar em uma competição.
¡ No entanto, utilizando grafos específicos, o problema permite soluções rápidas § O que permite que o problema tenha dimensões grandes.
¡ Elimina todos aqueles que não conhecem as soluções rápidas § No mínimo tomarão um TLE; § Ou então demorarão para codificar uma solução.
¡ Árvore § Grafo conectado e acíclico; ▪ O número de arestas é o número de vértices -‐1;
§ Contém um único caminho entre dois vértices! § Palavra-‐chave: Conectado.
¡ Menor caminho (origem única) § BFS ou DFS.
¡ Menor caminho (todos os pares) § BFS ou DFS usando cada vértice como origem.
¡ Grafo Euleriano § Grafo que possua um caminho ou um ciclo Euleriano;
§ Um caminho Euleriano visita cada aresta uma única vez;
§ Um ciclo Euleriano é um caminho Euleriano que começa e termina no mesmo vértice;
§ Palavra-‐chave: “Deve visitar cada aresta uma única vez”.
¡ Para verificar se um grafo não direcionado possui um ciclo Euleriano § Todos os vértices devem ter grau par.
¡ Para verificar se um grafo não direcionado possui um caminho Euleriano § Somente dois vértices podem ter grau ímpar.
¡ Grafo Bipartido § Palavras chave: “2 conjuntos”, “sem arestas em um mesmo conjunto”.
¡ Para determinar se um grafo conectado é bipartido ou não § Utilizamos a paridade das distâncias de um determinado vértice ▪ Haverá um conjunto com distâncias ímpares e outro com distâncias pares.
¡ Estão disponíveis dois conjuntos de códigos § Skiena (livro texto): em português; § NUS School of Computing: em inglês.
¡ O arquivo bfs-‐dfs.c possui uma implementação da BFS § Basta adaptar as funções processa_vertice() e processa_aresta(), de acordo com a necessidade.
¡ A função encontra_caminho() analisa a ordem de exploração dos vértices para encontrar o menor caminho entre dois vértices.
¡ O arquivo bfs-‐dfs.c possui uma implementação da DFS § Novamente, basta adaptar as funções processa_vertice() e processa_aresta(), de acordo com a necessidade.
¡ O arquivo findcycle.c analisa as arestas para detectar ciclos;
¡ O arquivo connected.c enumera os componentes conectados de um grafo.
¡ ch4_01_dfs.cpp § Implementação de DFS; § Floodfill; § Ordenação Topológica; § Algoritmo de Tarjan (Classificação de Arestas); § Pontos de Articulaçã0 e Pontes; § Detecção de Componentes Fortemente Conectados.
¡ ch4_04_bfs.cpp § Implementação de BFS; § Caracterização de grafos bipartidos; § Menor caminho de origem única.
Perguntas?
FIM