/* Reading the input graph */ void read_graph() { int e, i, u, v; /* read number of nodes and edges */ if (scanf("%d %d", &N_Vertex, &e) != 2) exit(EXIT_FAILURE); Vertices = (vertex_t*) malloc(N_Vertex * sizeof(vertex_t)); for (u = 0; u < N_Vertex; u++) { Vertices[u].first_edge = NULL; Vertices[u].parent = NULL; } for (i = 0; i < e; i++) { if (scanf("%d %d", &u, &v) != 2) exit(EXIT_FAILURE); add_new_edge(u, v); } }
/* dgraph_rnd_acyclic_parts() - create a random graph made up of acyclic parts. * n_trees - the number of acyclic parts. * tree_size - number of vertices per acyclic part. * branch_f - branching factor of acyclic parts. * ext_f - Number of additional external edges into each acylic parts root. * Note that each leaf vertex of a tree automatically causes the * creation of an edge to the root vertex of some tree. * The user should ensure that: * 1. tree_size > branch_f. (do not allow edge from a root vertex * to itself.) * 2. n_trees >= branch_f. * Otherwise the algorithm may run indefinitely trying to generate the graph. */ dgraph_t *dgraph_rnd_acyclic_parts(int n_trees, int tree_size, int branch_f, int ext_f) { dgraph_t *g; dgraph_vertex_t *vertex, *vertices; dgraph_edge_t *edge_ptr; int i, j, k, r, n; int v, w; int exists; int tree_start, tree_end; int child_start, child_end; int costDiff; int *stack, tos, *visited, vertex_count; /* For converting rand() result to edge costs. */ costDiff = (MaxEdgeCost - MinEdgeCost); /* Calculate the number of vertices in the graph. */ n = n_trees * tree_size; /* Stack and boolean array for reachability DFS. */ stack = malloc(n * sizeof(int)); visited = malloc(n * sizeof(int)); start_graph_gen: /* Allocate space for the graph. */ g = malloc(sizeof(dgraph_t)); vertices = g->vertices = malloc(n*sizeof(dgraph_vertex_t)); g->n = n; /* Initialise vertex entries in the graph structure. */ for(i = 0; i < n; i++) { vertices[i].first_edge = vertices[i].last_edge = NULL; } /* The root vertex of ac part i is located at i * tree_size in the array. * Here i ranges from 0 to n_trees - 1. */ /* Create edges for each ac part. */ for(i = 0; i < n_trees; i++) { tree_start = i * tree_size; tree_end = tree_start + tree_size; /* Cycle through each vertex in the ac part. */ for(j = 0; j < tree_size; j++) { v = tree_start + j; /* Array index for the jth vertex in the ac part. */ vertex = &vertices[v]; /* The immediate children of the jth vertex are at * branch_f * j + 1, branch_f * j + 2, ..., branch_f * j + branch_f * in the ac part. */ child_start = tree_start + branch_f * j + 1; child_end = child_start + branch_f; /* Create an edge from v to each child entry in the array. * If the ac part is not large enough to hold a child, an edge * from the child to a random root vertex is created. */ for(k = child_start; k < child_end; k++) { if(k < tree_end) { add_new_edge(vertex, k, MinEdgeCost + (rand() % costDiff)); } else { /* Select a random root vertex entry which is not already * in v's edge list. */ do { r = tree_size * (rand() % n_trees); /* Check that edge (v,r) does not already exist. */ exists = 0; edge_ptr = vertex->first_edge; while(edge_ptr) { if(edge_ptr->vertex_no == r) { exists = 1; break; } edge_ptr = edge_ptr->next; } } while(exists); add_new_edge(vertex, r, MinEdgeCost + (rand() % costDiff)); } } /* To make the acyclic structure, edges are created which point to * the grandchildren. */ child_start = tree_start + branch_f*(branch_f * j + 1) + 1; child_end = child_start + branch_f * branch_f; for(k = child_start; k < child_end; k++) { if(k < tree_end) { add_new_edge(vertex, k, MinEdgeCost + (rand() % costDiff)); } else { /* Select a random root vertex entry which is not already * in v's edge list. */ do { r = tree_size * (rand() % n_trees); /* Check that edge (v,r) does not already exist. */ exists = 0; edge_ptr = vertex->first_edge; while(edge_ptr) { if(edge_ptr->vertex_no == r) { exists = 1; break; } edge_ptr = edge_ptr->next; } } while(exists); add_new_edge(vertex, r, MinEdgeCost + (rand() % costDiff)); } } } } /* Create additional external edges into the root vertex of each ac part. */ for(i = 0; i < n_trees; i++) { for(j = 0; j < ext_f; j++) { /* The root vertex entry, w, is the desination. */ w = i * tree_size; /* Keep trying random source vertices until an edge that does not * already exist is found. */ do { /* Choose a source vertex, v, at random which is not equal to * w. */ v = rand() % (n-1); if(v >= w) v++; vertex = &vertices[v]; /* Check that edge (v,w) does not already exist. */ exists = 0; edge_ptr = vertex->first_edge; while(edge_ptr) { if(edge_ptr->vertex_no == w) { exists = 1; break; } edge_ptr = edge_ptr->next; } } while(exists); add_new_edge(vertex, w, MinEdgeCost + (rand() % costDiff)); } } /* Test reachability of vertices from StartVertex using a DFS. */ memset(visited, 0, n * sizeof(int)); vertex_count = 0; tos = 0; visited[StartVertex] = 1; stack[tos++] = StartVertex; while(tos) { v = stack[--tos]; vertex_count++; vertex = &vertices[v]; edge_ptr = vertex->first_edge; while(edge_ptr) { w = edge_ptr->vertex_no; if(!visited[w]) { visited[w] = 1; stack[tos++] = w; } edge_ptr = edge_ptr->next; } } if(vertex_count != n) { /* Not reachable, so try again. */ dgraph_free(g); goto start_graph_gen; } free(stack); free(visited); return g; }
/* dgraph_rnd_sparse() - creates a directed random graph with all vertices * reachable from the starting vertex. Parameter n is the size of the graph, * and parameter edge_factor is the average OUT set size for vertices. * Returns a pointer to the random graph created. * For freeing space used by the random graph see dgraph_free(). */ dgraph_t *dgraph_rnd_sparse(int n, double edge_factor) { int i, j, k, m; int *c, *size; int costDiff, n_edges, edge_count; dgraph_t *g; dgraph_vertex_t *vertex, *vertices; dgraph_edge_t *edge_ptr; /* Allocate space for the graph. */ g = malloc(sizeof(dgraph_t)); g->vertices = malloc(n*sizeof(dgraph_vertex_t)); g->n = n; /* Allocate space for temporary arrays. */ c = malloc(n * sizeof(int)); size = malloc(n * sizeof(int)); /* Initialise variables and arrays. */ costDiff = (MaxEdgeCost - MinEdgeCost); n_edges = edge_factor * n; vertices = g->vertices; for(i = 0; i < n; i++) { vertices[i].first_edge = NULL; vertices[i].last_edge = NULL; c[i] = i; size[i] = 1; } /* For each vertex except the starting vertex, set up one random edge * pointing to it. We do not set up a random edge pointing to the starting * vertex, that is, vertex number 0. */ for(j = 1; j < n; j++) { /* Choose one of the available 'from' verticies at random. */ k = rand() % (n - size[j]); /* Find the unused vertex, i, that corresponds to k. */ i = -1; m = -1; while(m < k) { i++; if(c[i] != c[j]) m++; } /* In order to avoid creating cycles in the sub-graph, we update the * array c[] to keep track of the connected parts in the sub-graph. * Do this by updating all verticies with connection number c[i] to * have connection number c[j]. */ m = c[i]; for(k = 0; k < n; k++) { if(c[k] == m) { c[k] = c[j]; size[k] += size[j]; } } /* Add the new edge to the random graph. */ add_new_edge(&vertices[i], j, MinEdgeCost + (rand() % costDiff)); } /* We are done with using c[] and size[]. */ free(c); free(size); /* Initialise edge_count and calculate the number of edges required. */ edge_count = n-1; n_edges = n * edge_factor; /* Create the random graph. Edges from vertex i to vertex j. * Variable k keeps track of the number of vertices in the out set * of the current vertex. */ while(edge_count < n_edges) { /* Select random i and j */ i = rand() % n; j = rand() % n; vertex = &vertices[i]; /* The cost for the edge from a vertex to itself is zero. */ if (i != j) { /* Scan the existing edges to make sure that an edge to j does not * already exist. */ edge_ptr = vertex->first_edge; while(edge_ptr) { if(edge_ptr->vertex_no == j) break; edge_ptr = edge_ptr->next; } /* If the edge to j does not already exist create the new edge. */ if(!edge_ptr) { add_new_edge(vertex, j, MinEdgeCost + (rand() % costDiff)); edge_count++; } } } return g; }
/* dgraph_rnd_dense() - creates a directed random graph with all vertices * reachable from the starting vertex. Parameter n is the size of the graph, * and parameter prob is the probability of edge existence. * Returns a pointer to the random graph created. */ dgraph_t *dgraph_rnd_dense(int n, double prob) { int i, j, k, m; int *c, *size; int *sources; double x; int costDiff; dgraph_t *g; dgraph_vertex_t *vertex, *vertices; /* Allocate space for the graph. */ g = malloc(sizeof(dgraph_t)); g->vertices = malloc(n*sizeof(dgraph_vertex_t)); g->n = n; /* Allocate space for temporary arrays. */ c = malloc(n * sizeof(int)); size = malloc(n * sizeof(int)); sources = malloc(n * sizeof(int)); /* Initialise variables and arrays. */ costDiff = (MaxEdgeCost - MinEdgeCost); vertices = g->vertices; for(i = 0; i < n; i++) { vertices[i].first_edge = NULL; vertices[i].last_edge = NULL; c[i] = i; size[i] = 1; sources[i] = UNDEFINED; } /* For each vertex, except the starting vertex, set up one random edge * pointing to it. We do not set up a random edge pointing to the starting * vertex, that is, vertex number 0. */ for(j = 1; j < n; j++) { /* Choose one of the available 'from' verticies at random. */ k = rand() % (n - size[j]); /* Find the unused vertex, i, that corresponds to k, and record the * connection in the array sources[]. */ i = -1; m = -1; while(m < k) { i++; if(c[i] != c[j]) m++; } sources[j] = i; /* In order to avoid creating cycles in the sub-graph, we update the * array c[] to keep track of the connected parts in the sub-graph. * Do this by updating all verticies with connection number c[i] to * have connection number c[j]. */ m = c[i]; for(k = 0; k < n; k++) { if(c[k] == m) { c[k] = c[j]; size[k] += size[j]; } } } /* We are done with using c[] and size[]. */ free(c); free(size); /* We note that we must change the probability of edge existence slightly * since n-1 edges have already been determined. */ prob = (prob*n - 1) / (n - 1); /* Create the random graph. Edges from vertex i to vertex j. * Variable k keeps track of the number of vertices in the out set * of the current vertex. */ for(i = 0; i < n; i++) { vertex = &vertices[i]; for(j = 0; j < n; j++) { /* Only create edges that are not from a vertex to itself. */ if (i != j) { /* Create and edge from vertex i to vertex j with probability * prob. All edges in the connecting sub-graph are created. */ x = (double) rand() / RAND_MAX; if (x <= prob || sources[j] == i) { add_new_edge(vertex, j, MinEdgeCost + (rand() % costDiff)); } } } } /* We are done with using sources[]. */ free(sources); return g; }