segunda-feira, 30 de novembro de 2015

Atividade de Laboratório 5 - LAB EXAME

Faaaala Professor!! Deboa?? É, como o tempo passa rápido né? Final de ano chegou voando e tamo ai com o ultimo Lab de CES 11 de 2015, é nóis!! Esse lab me ensinou a manipular grafos orientados utilizando listas de adjacência, além de me ensinar a aplicação dos Algoritmos de Tarjan e Dijkstra para o mesmo digrafo. Também utilizei a ordenação de listas.

Link para o vídeo: https://youtu.be/DlBCPXbcevM

Código Fonte:
#include <bits/stdc++.h>
#define infinito 9999999

using namespace std;

///implementação da estrutura de dados descrita no arquivo do lab

typedef int vertice;
typedef struct CelAdj CelAdj;
typedef struct Dijkstra_struct Dijkstra_struct;
typedef int* vetor;
typedef vetor* matriz;

struct Dijkstra_struct
{
    int** distancia;
    int** predecessor;
};

struct CelAdj
{
    vertice vert;
    int minutos;
    CelAdj *prox;
};
struct CelVert
{
    char aeroporto[30];
    CelAdj *listaAdj;
};
struct digrafo
{
    int nvert;
    CelVert *vertices;
};
digrafo G;

void Ordenar_listas();

void Memoria()
{
    G.vertices = (CelVert*)malloc(G.nvert*sizeof(CelVert));
    for(int i = 0; i< G.nvert; i++)
    {
        G.vertices[i].listaAdj = NULL;
    }
}
void Leitura(FILE* arqEntrada)
{
    int origem, destino, lig, tempo, rotas_minimas, destino1, destino2;
    CelAdj* aux;
    fscanf(arqEntrada,"%d ", &G.nvert);
    Memoria();
    for(int i = 0; i < G.nvert ; i++)
    {
        fgets(G.vertices[i].aeroporto, 30, arqEntrada);
    }
    fscanf(arqEntrada,"%d", &lig);
    for(int j = 0; j < lig; j++)
    {
        fscanf(arqEntrada,"%d %d %d", &origem, &destino, &tempo);
        aux = G.vertices[origem].listaAdj;
        if(aux != NULL)///se já houver alguem ligado ao vertice
        {
            for(; aux->prox != NULL; aux = aux->prox);
            aux->prox = (CelAdj*)malloc(sizeof(CelAdj));
            aux = aux->prox;
            aux -> vert = destino;
            aux -> minutos = tempo;
            aux ->prox = NULL;
        }
        else///se nao houver ninguem ligado ao vertice ainda
        {
            G.vertices[origem].listaAdj = (CelAdj*)malloc(sizeof(CelAdj));
            (G.vertices[origem].listaAdj)->vert = destino;
            (G.vertices[origem].listaAdj)->minutos = tempo;
            (G.vertices[origem].listaAdj)->prox = NULL;
        }
    }
    ///ordenação das listas de adjacência; ta ok!!!
}
void Printar_Grafo(FILE* saida)
{
    fprintf(saida,"Digrafo:\n");
    for(int i = 0; i < G.nvert; i++)
    {
        fprintf(saida,"%d (%s):",i, G.vertices[i].aeroporto);
        for(CelAdj* aux = G.vertices[i].listaAdj; aux != NULL; aux = aux->prox)
        {
            if(aux->prox != NULL)
                fprintf(saida," %d(%d)", aux->vert, aux -> minutos);
            if(aux->prox == NULL)
                fprintf(saida," %d(%d)\n", aux->vert, aux -> minutos);
        }
    }
}
void Ordenar_listas()///ordena as listas de adjacência de cada elemento do vetor de structs
{
    for(int i = 0; i < G.nvert; i++)
    {
        CelAdj* aux;
        aux = G.vertices[i].listaAdj;
        if(aux->prox == NULL)
        {
            return;
        }
        else
        {
            for(; aux->prox!=NULL; aux = aux->prox)
            {
                CelAdj* q = NULL;
                q = aux->prox;
                if(q->prox == NULL)
                {
                    return;
                }
                else
                {
                    q = aux->prox;
                    q = q->prox;
                    aux = aux->prox;
                    for(; q!=NULL; q = q->prox)
                        if(q->vert < aux->vert)
                        {
                            CelAdj x = *aux;
                            *aux = *q;
                            *q = x;
                        }
                }

            }
        }
    }
}
Dijkstra_struct Dijkstra() ///Preenche as matrizes de distancia e de predecessão, aplicando o algoritmo de Dijkstra n vezes
{
    Dijkstra_struct grafo;
    CelAdj *p;
    bool **analisado;
    int n = G.nvert, menor;

    analisado = (bool**)malloc(n*sizeof(bool*));
    grafo.distancia = (matriz)malloc(n*sizeof(vetor));
    grafo.predecessor = (matriz)malloc(n*sizeof(vetor));


    for(int i = 0; i < n; i++)
    {
        grafo.distancia[i] = (vetor)malloc(n*sizeof(int));
        grafo.predecessor[i] = (vetor)malloc(n*sizeof(int));
        analisado[i] = (bool*)malloc(n*sizeof(bool));
    }

    for(int i = 0; i < n; i++)
    {
        grafo.distancia[i][i] = 0;
        grafo.predecessor[i][i] = i;
        analisado[i][i] = false;
        for(int j = 0; j < n; j++)
        {
            if(i != j)
            {
                grafo.distancia[i][j] = infinito;
                grafo.predecessor[i][j] = -1;
                analisado[i][j] = false;
            }
        }
    }

    for(int i = 0; i < n; i++)
    {
        for(int t = 0; t < n; t++)
        {
            int k;
            for(k = 0; k < n; k++)
            {
                if(!analisado[i][k])
                {
                    menor = k;
                    break;
                }
            }
            for(int j = 0; j < n; j++)
            {
                if(grafo.distancia[i][j] < grafo.distancia[i][menor] && !analisado[i][j])
                    menor = j;
            }
            analisado[i][menor] = true;
            for(p = G.vertices[menor].listaAdj; p != NULL; p = p->prox)
            {
                if(grafo.distancia[i][p->vert] > grafo.distancia[i][menor] + p->minutos)
                {
                    grafo.distancia[i][p->vert] = grafo.distancia[i][menor] + p->minutos;
                    grafo.predecessor[i][p->vert] = menor;
                }
            }
        }
    }

    return grafo;
}
void Rota_Minima(FILE* entrada, FILE* saida, Dijkstra_struct grafo, int n)
{
    stack<int> pilha;
    int rotas, de, para, atual = 0;
    fscanf(entrada, "%d", &rotas);
    fprintf(saida, "Rotas minimas:\n");
    while (rotas > 0)
    {
        fscanf(entrada, "%d %d", &de, &para);
        fprintf(saida, "%d a %d: ", de, para);
        if(grafo.distancia[de][para] < infinito)
        {

            if(para != de)
            {

                fprintf(saida, "%d", de);
                atual = para;

                while(grafo.predecessor[de][atual] != de)
                {

                    pilha.push(atual);
                    atual = grafo.predecessor[de][atual];

                }

                pilha.push(atual);

                while(!pilha.empty())
                {

                    fprintf(saida, "-%d", pilha.top());
                    pilha.pop();

                }
                fprintf(saida, " (%d minutos)\n", grafo.distancia[de][para]);

            }
            else
                fprintf(saida, "(0 minutos)\n");

        }
        else
            fprintf(saida, "sem voos\n");
            rotas--;
    }
    fprintf(saida, "\n");
}
void DFS(int* pai, int *expl, int *comp, int *ce, int *cc, int v, FILE* saida)///auxilia no algoritmo de tarjan para encontrarmos trajetos fechados
{
    CelAdj *p;
    expl[v] = ++(*ce);
    for(p = G.vertices[v].listaAdj; p != NULL; p = p->prox)
    {
        if(expl[p->vert] == 0)
        {
            pai[p->vert] = v; /// Armazenamos os pais na árvore de exploração
            DFS(pai, expl, comp, ce, cc, p->vert, saida);
        }
        else if(expl[p->vert] < expl[v] && comp[p->vert] == 0)
        {
            stack<int> pilha;
            int atual = v;
            fprintf(saida, "%d", p->vert);
            ///invertemos a ordem da impressão
            while(atual != p->vert)
            {
                pilha.push(atual);
                atual = pai[atual];
            }
            while(!pilha.empty())
            {
                fprintf(saida, "-%d", pilha.top());
                pilha.pop();
            }
            fprintf(saida, "-%d\n", p->vert);
        }
    }
    comp[v] = ++(*cc);
}
void ciclos(FILE* saida)
{
    int *pai = (vetor)malloc(G.nvert*sizeof(int));
    int *expl = (vetor)malloc(G.nvert*sizeof(int));
    int *comp = (vetor)malloc(G.nvert*sizeof(int));
    int ce = 0, cc = 0;
    for(int i = 0; i < G.nvert; i++)
    {
        expl[i] = 0;
        comp[i] = 0;
        pai[i] = -1;
    }
    fprintf(saida, "Trajetos fechados:\n");
    for(int i = 0; i < G.nvert; i++)
    {
        if(expl[i] == 0)
            DFS(pai, expl, comp, &ce, &cc, i, saida);
    }
}
int main()
{
    FILE *entrada, *saida;
    entrada = fopen("entrada.txt", "r");
    saida = fopen("saida.txt", "w");
    Leitura(entrada);
    Ordenar_listas();
    Dijkstra_struct grafo = Dijkstra();
    Printar_Grafo(saida);
    Rota_Minima(entrada, saida, grafo, G.nvert);
    ciclos(saida);
    fclose(entrada);
    fclose(saida);
}

Nenhum comentário:

Postar um comentário