1
0

feat: Initial commit

This commit is contained in:
2024-03-22 17:37:24 +01:00
parent 4288bd63a1
commit 6732a7a166
120 changed files with 9620 additions and 0 deletions

View File

@@ -0,0 +1,414 @@
// Laboratorio 9 - Esercizio 1 - Graph.c
// Matteo Schiff - s295565
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include "Graph.h"
#include "ST.h"
typedef struct node *link;
struct node
{
int v;
int wt;
link next;
};
struct graph
{
int V;
int E;
link *ladj;
link z;
ST tab;
};
static link newNode(int v, int wt, link next)
{
link t = (link)malloc(sizeof(*t));
t->v = v;
t->wt = wt;
t->next = next;
return t;
}
static void freeList(link t, link z)
{
link q, x = t;
if (t == z)
return;
while (x != z)
{
q = x->next;
free(x);
x = q;
}
}
static int searchList(link t, link z, int v)
{
for (link x = t; x != z; x = x->next)
{
if (x->v == v)
return 1;
}
return 0;
}
static Edge EDGEcreate(int v, int w, int wt)
{
Edge e;
e.v = v;
e.w = w;
e.wt = wt;
return e;
}
void GRAPHedges(Graph G, Edge *a)
{
int v, E = 0;
link t;
for (v = 0; v < G->V; v++)
for (t = G->ladj[v]; t != G->z; t = t->next)
a[E++] = EDGEcreate(v, t->v, t->wt);
}
Graph GRAPHload(FILE *fin)
{
int V, i, id1, id2, wt;
char label1[MAX_LEN + 1], label2[MAX_LEN + 1];
Graph G;
fscanf(fin, "%d", &V);
G = GRAPHinit(V);
for (i = 0; i < V; i++)
{
fscanf(fin, "%s", label1);
STinsert(G->tab, label1);
}
while (fscanf(fin, "%s %s %d", label1, label2, &wt) == 3)
{
id1 = STsearch(G->tab, label1);
id2 = STsearch(G->tab, label2);
if (id1 >= 0 && id2 >= 0)
GRAPHinsertE(G, id1, id2, wt);
}
return G;
}
void GRAPHstore(Graph G, FILE *fout)
{
int i;
Edge *a;
a = malloc(G->E * sizeof(Edge));
GRAPHedges(G, a);
fprintf(fout, "%d\n", G->V);
for (i = 0; i < G->V; i++)
fprintf(fout, "%s\n", STsearchByIndex(G->tab, i));
for (i = 0; i < G->E; i++)
fprintf(fout, "%s %s %d\n",
STsearchByIndex(G->tab, a[i].v),
STsearchByIndex(G->tab, a[i].w), a[i].wt);
free(a);
}
void GRAPHinsertE(Graph G, int v, int w, int wt)
{
G->ladj[v] = newNode(w, wt, G->ladj[v]);
G->E++;
}
void GRAPHremoveE(Graph G, int v, int w)
{
link x, p;
for (x = G->ladj[v], p = NULL; x != G->z; p = x, x = x->next)
{
if (x->v == w)
{
if (x == G->ladj[v])
G->ladj[v] = x->next;
else
p->next = x->next;
break;
}
}
G->E--;
free(x);
}
static link *LISTinit(int V, link z)
{
link *list = (link *)malloc(V * sizeof(link));
for (int v = 0; v < V; v++)
list[v] = z;
return list;
}
Graph GRAPHinit(int V)
{
Graph G = malloc(sizeof *G);
G->V = V;
G->E = 0;
G->z = newNode(-1, -1, NULL);
G->ladj = LISTinit(V, G->z);
G->tab = STinit(V);
return G;
}
void GRAPHfree(Graph G)
{
int i;
for (i = 0; i < G->V; i++)
{
freeList(G->ladj[i], G->z);
}
free(G->ladj);
free(G->z);
STfree(G->tab);
free(G);
}
int GRAPHgetIndex(Graph G, char *item)
{
int id;
id = STsearch(G->tab, item);
if (id == -1)
{
id = STinsert(G->tab, item);
G->V++;
}
return id;
}
int GRAPHEdgeCount(Graph G)
{
return G->E;
}
// funzione che restituisce in `backEdges` tutti i vertici di tipo backward
void searchBackwardEdgesR(Graph G, Edge e, int *time,
int *pre, int *post, Edge *backEdges, int *backEdgesNum)
{
pre[e.w] = (*time)++;
for (link t = G->ladj[e.w]; t != G->z; t = t->next)
if (pre[t->v] == -1)
searchBackwardEdgesR(G, EDGEcreate(e.w, t->v, t->wt), time, pre, post, backEdges, backEdgesNum);
else
{
if (post[t->v] == -1)
backEdges[(*backEdgesNum)++] = EDGEcreate(e.w, t->v, t->wt);
}
post[e.w] = (*time)++;
}
void GRAPHFindCardMinDAG(Graph G, int *cardinality, Edge *edges)
{
int *pre = (int *)malloc(G->V * sizeof(int));
int *post = (int *)malloc(G->V * sizeof(int));
Edge **backEdges = malloc(G->V * sizeof(Edge *));
int *cards = (int *)malloc(G->V * sizeof(int));
for (int i = 0; i < G->V; i++)
{
backEdges[i] = malloc(G->E * sizeof(Edge));
for (int j = 0; j < G->E; j++)
{
backEdges[i][j] = EDGEcreate(0, 0, 0);
}
}
int minCard = -1;
for (int i = 0; i < G->V; i++)
{
int time = 0;
cards[i] = 0;
for (int j = 0; j < G->V; j++)
{
pre[j] = -1;
post[j] = -1;
}
// per rendere un grafo un DAG bisogna togliere tutti gli archi backward
searchBackwardEdgesR(G, EDGEcreate(i, i, 0), &time, pre, post, backEdges[i], &cards[i]);
for (int j = 0; j < G->V; j++)
if (pre[j] == -1)
searchBackwardEdgesR(G, EDGEcreate(j, j, 0), &time, pre, post, backEdges[i], &cards[i]);
// inizio a memorizzare la cardinalità minima
if (cards[i] < minCard || minCard == -1)
{
minCard = cards[i];
}
}
free(post);
free(pre);
int curWeight, idMaxWeight = 0, maxWeight = -1;
if (minCard == 0)
{
puts("Il grafo è già un DAG, non si deve fare nulla");
*cardinality = 0;
}
else
{
puts("Insiemi di archi da rimuovere con cardinalità minima: ");
for (int i = 0; i < G->V; i++)
{
curWeight = 0;
if (cards[i] != minCard)
continue;
printf("{");
for (int j = 0; j < G->E; j++)
{
if (backEdges[i][j].wt != 0)
{
curWeight += backEdges[i][j].wt;
printf(" (%s, %s, wt: %d)", STsearchByIndex(G->tab, backEdges[i][j].v), STsearchByIndex(G->tab, backEdges[i][j].w), backEdges[i][j].wt);
}
}
// mentre stampo gli insiemi cerco l'insieme di peso massimo
if (curWeight > maxWeight)
{
maxWeight = curWeight;
idMaxWeight = i;
}
printf(" }\n");
}
printf("Insieme di archi da rimuovere a peso massimo:\n {");
for (int i = 0; i < cards[idMaxWeight]; i++)
{
edges[i] = backEdges[idMaxWeight][i];
printf(" (%s, %s, wt: %d)", STsearchByIndex(G->tab, backEdges[idMaxWeight][i].v), STsearchByIndex(G->tab, backEdges[idMaxWeight][i].w), backEdges[idMaxWeight][i].wt);
}
printf(" }\n");
*cardinality = cards[idMaxWeight];
}
for (int i = 0; i < G->V; i++)
{
free(backEdges[i]);
}
free(backEdges);
free(cards);
}
void GRAPHRemoveEdges(Graph G, Edge *edges, int N)
{
for (int i = 0; i < N; i++)
GRAPHremoveE(G, edges[i].v, edges[i].w);
}
static int GRAPHisSource(Graph G, int id)
{
// un nodo è sorgente se nessun arco punta a tale nodo
for (int v = 0; v < G->V; v++)
{
for (link t = G->ladj[v]; t != G->z; t = t->next)
{
if (t->v == id)
{
// ho trovato un arco che punta al nodo
return 0;
}
}
}
return 1;
}
void sortTopologicalR(Graph G, int w, int *time,
int *pre, int *post, int *orderedVertex, int *cnt)
{
pre[w] = (*time)++;
for (link t = G->ladj[w]; t != G->z; t = t->next)
if (pre[t->v] == -1)
sortTopologicalR(G, t->v, time, pre, post, orderedVertex, cnt);
post[w] = (*time)++;
orderedVertex[(*cnt)++] = w;
}
void sortTopological(Graph G, int start, int *orderedVertex)
{
int time = 0, cnt = 0;
int *pre = (int *)malloc(G->V * sizeof(int));
int *post = (int *)malloc(G->V * sizeof(int));
for (int j = 0; j < G->V; j++)
{
pre[j] = -1;
post[j] = -1;
}
sortTopologicalR(G, start, &time, pre, post, orderedVertex, &cnt);
free(post);
free(pre);
}
void GRAPHmaxPathFromSource(Graph G)
{
link t;
int *distances = (int *)malloc(G->V * sizeof(int));
int *st = (int *)malloc(G->V * sizeof(int));
int *topSorted = (int *)malloc(G->V * sizeof(int));
for (int i = 0; i < G->V; i++)
{
if (GRAPHisSource(G, i))
{
// ordinamento topologico dei vertici a partire dalla sorgente i
sortTopological(G, i, topSorted);
for (int j = 0; j < G->V; j++)
{
distances[j] = INT_MIN;
st[j] = -1;
}
distances[i] = 0;
st[i] = i;
for (int j = G->V-1; j >=0; j--)
{
int k = topSorted[j];
for (t = G->ladj[k]; t != G->z; t = t->next)
{
// aggiorno le distanze se ho trovato un cammino più lungo
if (distances[t->v] < distances[k] + t->wt)
{
st[t->v] = k;
distances[t->v] = distances[k] + t->wt;
}
}
}
// stampo per ogni vertice il cammino massimo
for (int j = 0; j < G->V; j++)
{
int k = j;
if (j != i)
{
printf("Cammino massimo dalla sorgente %s al nodo %s:\n", STsearchByIndex(G->tab, i), STsearchByIndex(G->tab, j));
printf("%s", STsearchByIndex(G->tab, k));
while (k != i)
{
printf(" <- %s", STsearchByIndex(G->tab, st[k]));
k = st[k];
}
printf("\nPeso del cammino: %d\n", distances[j]);
}
}
}
}
free(distances);
free(topSorted);
free(st);
}