CES-11 ALGORITMOS E ESTRUTURAS DE DADOS Aulas Práticas

Propaganda
CES-11 ALGORITMOS E
ESTRUTURAS DE DADOS
Aulas Práticas - 2016
Capítulo V
Grafos

O presente trabalho corresponde ao laboratório do Exame
de CES-11/2016

Além deste trabalho, o referido exame terá ainda uma prova
feita em sala de aula

Para compor a nota do Exame, o peso do trabalho será igual
ao peso da prova
Objetivos deste laboratório:
1. Ler e armazenar um digrafo numa estrutura com listas de
adjacências

O digrafo deve ter uma informação inteira e positiva em
cada um de seus vértices (duração da tarefa representada
pelo vértice)
2. Testar se o digrafo armazenado é cíclico ou acíclico
3. Se o digrafo for acíclico, encarando-o como o cronograma
das tarefas de um projeto:


Calcular o tempo mínimo de término desse projeto
Encontrar as tarefas e os arcos dos caminhos críticos do
digrafo (pode haver mais de um)
4. Se for cíclico, encontrar os vértices e os arcos de cada um
de seus componentes fortemente conexos

Observação: o programa elaborado deverá ler os dados de
vários digrafos e, para cada um, realizar os 4 passos
anteriores
Exercício 5.1: Leitura e armazenamento de digrafos
Fazer um programa para:

Ler um digrafo, com uma informação inteira e positiva em
cada um seus vértices (duração da tarefa representada pelo
vértice)

Armazenar o digrafo numa estrutura com listas de
adjacências

Imprimir todo o conteúdo de sua estrutura com lista de
adjacências
Declarações para digrafos:
15
12
typedef
typedef
typedef
typedef
2
10
int vertice;
struct CelulaAdj CelulaAdj;
20
struct CelulaVertice CelulaVertice;
struct Grafo Grafo;
struct CelulaAdj {
vertice vert;
CelulaAdj *prox;
};
G
1
15
2
12
3
10
4
12
5
20
EspacoVertices
1
12
3
4
5
2
5
4

4


1
5

3

nvert
5
struct CelulaVertice {
int duracao;
CelulaAdj *listadj;
};
15
12
2
struct Grafo {
CelulaVertice *EspacoVertices;
int nvert;
};
/* Variaveis globais */
Grafo G;
A ser alocado
dinamicamente
(malloc)
G
10
20
1
15
2
12
3
10
4
12
5
20
EspacoVertices
1
12
3
4
5
2
5
4

4


1
5

3

nvert
5
/*
Prototipos de funcoes
*/
O grafo a ser lido e escrito
é G (variável global)
void LerGrafo (void);
void ImprimirGrafo (void);
/*
Programa Principal:
*/
void main () {
printf ("Leitura do Grafo G:\n\n");
LerGrafo ();
printf ("\nGrafo G em fase inicial\n");
ImprimirGrafo ();
printf ("\n\n"); system ("pause"); return 0;
}
Observação: no Capítulo VI das aulas teóricas, há um algoritmo
para leitura e armazenamento de grafos em listas de adjacências
Ele pode ser adaptado para este trabalho
Exemplo: para o digrafo
Possível conteúdo impresso:
15
12
Grafo G em fase inicial
2
10
1
12
3
4
Numero de vertices: 5
1) duracao: 15
adjs
: 2, 4
20
2) duracao: 12
adjs
: 5
3) duracao: 10
adjs
: 1, 4
4) duracao: 12
adjs
: 5
5) duracao: 20
adjs
: 3
G
1
15
2
12
3
10
4
12
5
20
EspacoVertices
5
2
5
4

4


1
5

3

nvert
5
Exercício 5.2: Construção da lista de contra-adjacências de
cada vértice (substitui o grafo reverso)

Contra-adjacente de um vértice v é um vértice do qual v é
adjacente

No programa anterior:
Acrescentar o campo listcontradj ao tipo CelulaVertice
struct CelulaVertice {
int duracao;
CelulaAdj *listadj, *listcontradj;
};
e formar a lista de contra-adjacências de cada vértice do grafo
Exemplo: no grafo anterior
15
12
1
10
2
3
sua estrutura com
as contra-adjacências
15
2
4
3

5


2
12
3
10
1
4
12
5

5

5
20
G
EspacoVertices
1
4
1
3
2
4
5
20
1
12


3

4


nvert
5
Exercício 5.3: Teste de aciclicidade para digrafos

No programa do exercício anterior, testar se o digrafo lido é
cíclico ou acíclico

Para tanto procurar arcos de volta no digrafo durante uma
busca em profundidade; encontrando um, o grafo é cíclico,
caso contrário, é acíclico
Observação: no Capítulo VII das aulas teóricas, há um algoritmo
para realizar o teste de aciclicidade – pode-se adaptá-lo
Lá usa-se uma variável global aciclico para denotar a aciclicidade,
mas neste exercício essa variável deve ser um campo da struct
grafo

Acrescentar o campo aciclico ao tipo grafo:
struct Grafo {
12
CelulaVertice *EspacoVertices;
int nvert;
logic aciclico;
};
1
15
2
2
4
3

5


3
10
1
4
12
5

5

G
EspacoVertices
1
3
2
4
5

aciclico
4
1
12
3
20
12
20
1
10
2
5
15
False

3

4


nvert
5
Teste de aciclicidade para digrafos

Manter, para o vértice que está sendo visitado, uma pilha com
todos os seus ancestrais, incluindo ele próprio

Partindo dele, para visitar seus adjacentes, se um deles, já
visitado, pertencer a tal pilha, existe o arco de volta

Quando todos os seus adjacentes já tiverem sido visitados,
retirá-lo da pilha de ancestrais

Caso seja encontrado um ciclo, marcar o campo aciclico de
G como sendo FALSE
Acrescentar o campo visit ao tipo CelulaVertice:
struct CelulaVertice {
int duracao; logic visit;
CelulaAdj *listadj, *listcontradj;
};

Declarações, protótipos e funções para pilhas de vértices:
typedef struct noh noh;
typedef noh *pilha;
typedef noh *pontpilha;
struct noh {vertice elem; noh *prox;};
void Empilhar (vertice, pilha*);
void Desempilhar (pilha*);
vertice Topo (pilha);
void InicPilha (pilha*);
logic Vazia (pilha);
void InicPilha (pilha *P)
{ *P = NULL;}
logic Vazia (pilha P) {
if (P == NULL) return TRUE;
else return FALSE;
}
void Empilhar (vertice x, pilha *P) {
noh *temp;
temp = *P; *P = (noh *) malloc (sizeof (noh));
(*P)->elem = x; (*P)->prox = temp;
}
É necessária ainda uma
função para procurar um
vértice na pilha de ancestrais
void Desempilhar (pilha *P) {
noh *temp;
if (! Vazia (*P)) {
temp = *P; *P = (*P)->prox; free (temp); }
else printf ("\n\tDelecao em pilha vazia\n");
}
vertice Topo (pilha P) {
if (! Vazia (P)) return P->elem;
else printf ("\n\tTopo de pilha vazia\n");
return -1;
}
Exercício 5.4: Se o digrafo for acíclico:

Encará-lo como o cronograma das tarefas de um projeto

Encontrar e imprimir o tempo mínimo de término de cada
tarefa e do projeto como um todo

Marcar os vértices e os arcos pertencentes aos caminhos
críticos do digrafo, imprimindo-os
Sugestão: implementar o algoritmo e a estratégia
apresentados no Capítulo VII das aulas teóricas
Poderão ser acrescentados novos campos às
structs CelulaVertice e CelulaAdj
Exercício 5.5: Se o digrafo for cíclico:

Encontrar os seus componentes fortemente conexos

Numerar cada vértice e cada arco do digrafo com o número
do componente fortemente conexo ao qual pertence

Imprimir os vértices e os arcos de cada um desses
componentes
Usar o algoritmo de Kosaraju apresentado no
Capítulo VII das aulas teóricas
Poderão ser acrescentados novos campos às
structs CelulaVertice e CelulaAdj
Download