From bbafa9b2105fbdce91ebc2db1a36963a7fb86f35 Mon Sep 17 00:00:00 2001 From: "Paulo H. Lamounier" <53798700+Nanashii76@users.noreply.github.com> Date: Tue, 25 Jun 2024 21:01:48 -0300 Subject: [PATCH] Some studies of graphs in dsa2 course --- dsa2_course/intro.c | 110 +++++++++++ dsa2_course/introGraph_matrix.c | 82 ++++++++ dsa2_course/problemsets/BFSofGraph.cpp | 21 ++ dsa2_course/problemsets/DFSofGraph.cpp | 18 ++ .../problemsets/componentesConectados.c | 126 ++++++++++++ dsa2_course/problemsets/distMin.c | 185 ++++++++++++++++++ dsa2_course/problemsets/ordemTopologica.c | 73 +++++++ dsa2_course/problemsets/printAdjacency.cpp | 13 ++ dsa2_course/problemsets/teste.txt | 9 + 9 files changed, 637 insertions(+) create mode 100644 dsa2_course/intro.c create mode 100644 dsa2_course/introGraph_matrix.c create mode 100644 dsa2_course/problemsets/BFSofGraph.cpp create mode 100644 dsa2_course/problemsets/DFSofGraph.cpp create mode 100644 dsa2_course/problemsets/componentesConectados.c create mode 100644 dsa2_course/problemsets/distMin.c create mode 100644 dsa2_course/problemsets/ordemTopologica.c create mode 100644 dsa2_course/problemsets/printAdjacency.cpp create mode 100644 dsa2_course/problemsets/teste.txt diff --git a/dsa2_course/intro.c b/dsa2_course/intro.c new file mode 100644 index 0000000..82386ad --- /dev/null +++ b/dsa2_course/intro.c @@ -0,0 +1,110 @@ +#include +#include +#include +#include + +// // Implementando um grafo com matriz de adjacência +// typedef struct grafo { +// int **adj; +// int v; +// } grafo; + +// // criando um grafo +// grafo *cria_grafo(int n) { +// grafo *g = malloc(sizeof(grafo)); +// g->v = n; +// g->adj = malloc(sizeof(int) * n); + +// for(int i = 0; i < n; ++i) { +// g->adj[i] = malloc(sizeof(int) * n); +// for(int j = 0; j < n; ++j) +// g->adj[i][j] = 0; +// } + +// return g; +// } + +// // destruindo um grafo +// void destroi_grafo(grafo *g) { +// for(int i = 0; i < g->v; ++i) +// free(g->adj[i]); +// free(g->adj); +// free(g); +// } + +// // grau do vértice +// int grau(grafo *g, int v) { +// int grau = 0; +// for(int u = 0; u < g->v; ++u) +// if(g->adj[v][u]) +// ++grau; +// return grau; +// } + +// // imprimindo recomendações +// void imprime_recomendacao(grafo *g, int v) { +// for(int u = 0; u < g->v; ++u) { +// if(g->adj[v][u]) +// for(int w = 0; w < g->v; ++w) +// if(g->adj[u][w] and w != v and (not g->adj[v][w])) +// printf("%d ", w); +// } + +// printf("\n"); +// } + +// Implementando grafos com lista de adjâcência +typedef struct no { + int v; + struct no *next; +} no; + +typedef struct grafo { + no **adj; + int v; +} grafo; + + +// criando um grafo / inicializando um grafo +grafo *cria_grafo(int n) { + grafo *g = malloc(sizeof(grafo)); + g->v = n; + g->adj = malloc(sizeof(no) * n); + + for(int i = 0; i adj[i] = NULL; + + return g; +} + +// inserir no início da lista de um no adjâscente +no *insere_list(no *list, int v) { + no *novo = malloc(sizeof(no)); + novo->v = v; + novo->next = list; + return novo; +} + +// inserindo uma aresta em um grafo não direcionado +void insere_aresta(grafo *g, int v, int u) { + g->adj[v] = insere_list(g->adj[v],u); + g->adj[u] = insere_list(g->adj[u],v); +} + +// imprimindo um grafo +void imprime_grafo(grafo *g) { + for(int v = 0; v < g->v; ++v) { + no *adj = g->adj[v]; + printf("%d -> ", v); + while(adj) { + printf("%d ", adj->v); + adj = adj->next; + } + printf("\n"); + } +} + + +int main(void) { + return 0; +} diff --git a/dsa2_course/introGraph_matrix.c b/dsa2_course/introGraph_matrix.c new file mode 100644 index 0000000..9a774cf --- /dev/null +++ b/dsa2_course/introGraph_matrix.c @@ -0,0 +1,82 @@ +// Introdução à grafos, principais funções e implementação com matrix de adjacência +#include +#include +#include + +// Definindo algumas estruturas importantes para auxiliar na criação do Grafo +typedef struct {int v; int w;} Edge; + +// Função para criar um par de arestas +Edge *edge(int x, int y) { + + Edge *ed = malloc(sizeof(Edge)); + ed->v = x; + ed->w = y; + + return ed; +} + +typedef struct Graph{ + int v, e; + int **adj; + +} graph; + +// Criando um grafo e alocando uma matrix de forma dinâmica +graph *GraphInit(int v) { + + graph *g = malloc(sizeof(graph)); + g->v = v; + g->e = 0; + g->adj = malloc(sizeof(int*) *v); + for(int i = 0; i < v; ++i) { + g->adj[i] = malloc(sizeof(int)*v); + g->adj[i] = 0; + } + + return g; +} + + +// Implementando uma função para adicioanr arestas em um grafo já inicializado +void GraphInsertEd(graph *g, Edge e, int dir) { + + // Se não for um digrafo, então é bidirecional + if((not dir) and (not g->adj[e.v][e.w])) { + g->adj[e.v][e.w] = 1; + g->adj[e.w][e.v] = 1; + g->e++; + } else if(dir and (not g->adj[e.v][e.w])) { + g->adj[e.v][e.w] = 1; + g->e++; + } + +} + +// Implementando uma função para remover uma aresta do grafo +void GraphRemoveEd(graph *g, Edge e, int dir) { + + // Se não for um digrafo, então é bidirecional + if((not dir) and (g->adj[e.v][e.w])) { + g->adj[e.v][e.w] = 0; + g->adj[e.v][e.w] = 0; + g->e--; + } else if(dir and (g->adj[e.v][e.w])) { + g->adj[e.v][e.w] = 0; + g->e--; + } + +} + +// Implemetando uma função para retornar um vetor de arestas presentes no grafo +int *GraphEdges(Edge e[], graph *g) { + + int idx = 0; + for(int v = 0; v < g->v; ++v) + for(int w = v+1; w < g->v; ++w) + if(g->adj[v][w]) { + e[idx++] = *edge(v,w); + } + + return idx; +} \ No newline at end of file diff --git a/dsa2_course/problemsets/BFSofGraph.cpp b/dsa2_course/problemsets/BFSofGraph.cpp new file mode 100644 index 0000000..e46d050 --- /dev/null +++ b/dsa2_course/problemsets/BFSofGraph.cpp @@ -0,0 +1,21 @@ +#include +using namespace std; + +vector bfsOfGraph(int V, vector adj[]) { + vector vis(V,0), ans; + vis[0] = 1; + queue q; + q.push(0); + + while(not q.empty()) { + int vertice = q.front(); + q.pop(); + + ans.emplace_back(vertice); + for(auto x : adj[vertice]) if (not vis[x]) { + vis[x] = 1; + q.push(x); + } + } + return ans; +} \ No newline at end of file diff --git a/dsa2_course/problemsets/DFSofGraph.cpp b/dsa2_course/problemsets/DFSofGraph.cpp new file mode 100644 index 0000000..3baf522 --- /dev/null +++ b/dsa2_course/problemsets/DFSofGraph.cpp @@ -0,0 +1,18 @@ +#include +using namespace std; + +void dfs(int v, vector adj[], vector& vis, vector& ans) { + vis[v] = 1; + ans.push_back(v); + for (int u : adj[v]) { + if (!vis[u]) { + dfs(u, adj, vis, ans); + } + } +} + +vector dfsOfGraph(int V, vector adj[]) { + vector vis(V, 0), ans; + dfs(0, adj, vis, ans); + return ans; +} \ No newline at end of file diff --git a/dsa2_course/problemsets/componentesConectados.c b/dsa2_course/problemsets/componentesConectados.c new file mode 100644 index 0000000..e5b9f1e --- /dev/null +++ b/dsa2_course/problemsets/componentesConectados.c @@ -0,0 +1,126 @@ +/* +Problema: Componentes Conectados em um Grafo + +Descrição: + +Você deve implementar um programa em C que encontre e liste todos os componentes conectados de um grafo não direcionado. + +Entrada: + + O número de vértices V no grafo. + O número de arestas E no grafo. + As próximas E linhas contêm dois inteiros u e v representando uma aresta entre o vértice u e o vértice v. + +Saída: + + O número de componentes conectados no grafo. + Para cada componente conectado, liste os vértices pertencentes a esse componente. + +Exemplo de Entrada: + +6 +5 +0 1 +0 2 +1 2 +3 4 +4 5 + +Exemplo de Saída: + +Número de componentes conectados: 2 +Componente 1: 0 1 2 +Componente 2: 3 4 5 +*/ +#include +#include +#include + +// Definição das estruturas de dados para o grafo +typedef struct no { + int v; + struct no* next; +} no; + +typedef struct grafo { + no **adj; + int n; +} grafo; + +// Função para criar um novo grafo +grafo *cria_grafo(int v) { + grafo *g = malloc(sizeof(grafo)); + g->n = v; + g->adj = malloc(v * sizeof(no*)); + + for(int i = 0; i < v; ++i) + g->adj[i] = NULL; + + return g; +} + +// Função para inserir um novo nó na lista de adjacência +no *insere_list(no *list, int u) { + no *novo = malloc(sizeof(no)); + novo->v = u; + novo->next = list; + return novo; +} + +// Função para inserir uma aresta no grafo +void insere_aresta(grafo *g, int u, int v) { + g->adj[u] = insere_list(g->adj[u], v); + g->adj[v] = insere_list(g->adj[v], u); +} + +// Função de busca em profundidade (DFS) para encontrar componentes conectados +void dfs(grafo *g, int v, int *vis, int *comp, int count) { + vis[v] = 1; + comp[v] = count; + no *adj = g->adj[v]; + while(adj) { + if (not vis[adj->v]) { + dfs(g, adj->v, vis, comp, count); + } + adj = adj->next; + } +} + +int main(void) { + int v, e; + scanf("%d %d", &v, &e); + + grafo *G = cria_grafo(v); + int *vis = calloc(v, sizeof(int)); + int *components = calloc(v, sizeof(int)); + int count = 0; + + // Lendo as arestas + for (int i = 0; i < e; ++i) { + int u, w; + scanf("%d %d", &u, &w); + insere_aresta(G, u, w); + } + + // Encontrando componentes conectados + for (int i = 0; i < v; ++i) { + if (not vis[i]) { + dfs(G, i, vis, components, count); + ++count; + } + } + + // Imprimindo os resultados + printf("Numero de componentes conectados: %d\n", count); + for (int a = 0; a < count; ++a) { + printf("Componente %d: ", a + 1); + for (int i = 0; i < v; ++i) { + if (components[i] == a) { + printf("%d ", i); + } + } + printf("\n"); + } + + return 0; +} diff --git a/dsa2_course/problemsets/distMin.c b/dsa2_course/problemsets/distMin.c new file mode 100644 index 0000000..55fc650 --- /dev/null +++ b/dsa2_course/problemsets/distMin.c @@ -0,0 +1,185 @@ +/* +Problema: Distância Mínima em um Grafo Não Ponderado + +Descrição: + +Você deve implementar um programa em C que encontre a distância mínima (em número de arestas) entre dois vértices em um grafo não direcionado e não ponderado. + +Entrada: + + O número de vértices V no grafo. + O número de arestas E no grafo. + As próximas E linhas contêm dois inteiros u e v representando uma aresta entre o vértice u e o vértice v. + Dois inteiros src e dest representando o vértice de origem e o vértice de destino, respectivamente. + +Saída: + + A distância mínima (em número de arestas) entre src e dest. + Se src e dest não estiverem conectados, imprima -1. + +Exemplo de Entrada: + +6 +7 +0 1 +0 2 +1 2 +1 3 +2 3 +3 4 +4 5 +0 5 + +Exemplo de Saída: + +4 + +Detalhes da Implementação: + + Use uma representação de lista de adjacência para armazenar o grafo. + Use uma função BFS para encontrar a distância mínima entre os dois vértices. +*/ + +#include +#include +#include + +// Estrutura de dados para a fila +typedef struct QueueNode { + int data; + struct QueueNode* next; +} QueueNode; + +typedef struct Queue { + QueueNode *front, *rear; +} Queue; + +// Função para criar uma nova fila +Queue* createQueue() { + Queue* q = (Queue*)malloc(sizeof(Queue)); + q->front = q->rear = NULL; + return q; +} + +// Função para criar um novo nó na fila +QueueNode* newQueueNode(int data) { + QueueNode* temp = (QueueNode*)malloc(sizeof(QueueNode)); + temp->data = data; + temp->next = NULL; + return temp; +} + +// Função para adicionar um elemento à fila +void enqueue(Queue* q, int data) { + QueueNode* temp = newQueueNode(data); + if (q->rear == NULL) { + q->front = q->rear = temp; + return; + } + q->rear->next = temp; + q->rear = temp; +} + +// Função para remover um elemento da fila +int dequeue(Queue* q) { + if (q->front == NULL) { + return -1; // Fila vazia + } + QueueNode* temp = q->front; + int data = temp->data; + q->front = q->front->next; + if (q->front == NULL) { + q->rear = NULL; + } + free(temp); + return data; +} + +// Função para verificar se a fila está vazia +int isEmpty(Queue* q) { + return q->front == NULL; +} + +// Implementando um grafo com lista de adjacência +typedef struct no { + int v; + struct no *next; +} no; + +typedef struct grafo { + no **adj; + int n; +} grafo; + +grafo *cria_grafo(int v) { + grafo *g = malloc(sizeof(grafo)); + g->n = v; + g->adj = malloc(sizeof(no) * v); + + for(int i = 0; i < v; ++i) + g->adj[i] = NULL; + + return g; +} + +no *cria_lista(no *list, int u) { + no *novo = malloc(sizeof(no)); + novo->v = u; + novo->next = list; + return novo; +} + +void cria_aresta(grafo *g, int u, int v) { + g->adj[u] = cria_lista(g->adj[u], v); + g->adj[v] = cria_lista(g->adj[v], u); +} + +void bfs(grafo *g, int v, int *vis, int *dist){ + vis[v] = 1; + dist[v] = 0; + Queue *q = createQueue(); + enqueue(q,v); + + while(not isEmpty(q)) { + int vertice = dequeue(q); + no* adj = g->adj[vertice]; + while(adj) { + if(not vis[adj->v]) { + vis[adj->v] = 1; + dist[adj->v] = dist[vertice] + 1; + enqueue(q,adj->v); + } + adj = adj->next; + } + } +} + + +int main(void) { + + int v, e; + scanf("%d %d", &v, &e); + + grafo *g = cria_grafo(v); + int *vis = calloc(v, sizeof(int)); + int *dist = calloc(v, sizeof(int)); + + while(e--) { + int u, v; + scanf("%d %d", &u, &v); + cria_aresta(g,u,v); + } + + int x,y; + scanf("%d %d", &x, &y); + + bfs(g,x,vis,dist); + + if (dist[y] == 0 and x != y) { + printf("-1\n"); // Não conectado + } else { + printf("%d\n", dist[y]); + } + + return 0; +} \ No newline at end of file diff --git a/dsa2_course/problemsets/ordemTopologica.c b/dsa2_course/problemsets/ordemTopologica.c new file mode 100644 index 0000000..4053397 --- /dev/null +++ b/dsa2_course/problemsets/ordemTopologica.c @@ -0,0 +1,73 @@ +/* + Imprimir a ordem topologia de um DAG +*/ +#include +#include +#include + +typedef struct no { + int v; + struct no *next; +} no; + +typedef struct grafo { + no **adj; + int n; +} grafo; + +grafo *cria_grafo(int v) { + grafo *g = malloc(sizeof(grafo)); + g->n = v; + g->adj = malloc(sizeof(no) * v); + + for(int i = 0; i < v; ++i) + g->adj[i] = NULL; + + return g; +} + +no *cria_lista(no *list, int u) { + no* novo = malloc(sizeof(no)); + novo->v = u; + novo->next = list; + return novo; +} + +void cria_aresta(grafo *g, int u ,int v) { + g->adj[u] = cria_lista(g->adj[u],v); +} + +void dfs(grafo *g, int *vis, int v) { + + vis[v] = 1; + for(no *adj = g->adj[v]; adj != NULL; adj = adj->next) + if(not vis[adj->v]) + dfs(g, vis, adj->v); + + printf("%d ", v); +} + +void ordenacao_topologica(grafo *g) { + int *vis = calloc(g->n, sizeof(int)); + for(int v = 0; v < g->n; ++v) + if(not vis[v]) + dfs(g,vis,v); + + free(vis); + printf("\n"); +} + +int main(void) { + int v,e; + scanf("%d %d", &v, &e); + grafo *g = cria_grafo(v); + + while(e--) { + int u, w; + scanf("%d %d", &u, &w); + cria_aresta(g,u,w); + } + + ordenacao_topologica(g); + return 0; +} \ No newline at end of file diff --git a/dsa2_course/problemsets/printAdjacency.cpp b/dsa2_course/problemsets/printAdjacency.cpp new file mode 100644 index 0000000..94254c0 --- /dev/null +++ b/dsa2_course/problemsets/printAdjacency.cpp @@ -0,0 +1,13 @@ +#include +using namespace std; + +vector> printGraph(int V, vector>edges) { + vector> ans(V); + + for(auto it : edges) { + ans[it.first].emplace_back(it.second); + ans[it.second].emplace_back(it.first); + } + + return ans; +} \ No newline at end of file diff --git a/dsa2_course/problemsets/teste.txt b/dsa2_course/problemsets/teste.txt new file mode 100644 index 0000000..e65cd74 --- /dev/null +++ b/dsa2_course/problemsets/teste.txt @@ -0,0 +1,9 @@ +6 +7 +5 2 +5 0 +4 0 +4 1 +2 3 +3 1 +0 1 \ No newline at end of file