<Rand.H>=
// File: Rand.H
// Last Revision: 23-Mar-2001
// Description: functions for the generation of random values.
//
// Note: The two functions myrand() and smyrand() were written by Dell'Amico
// using the portable pseudorandom generator RnG (see below).
#ifndef _RAND_H
#define _RAND_H
float myrand();
float smyrand(int seed);
int lprand();
int sprand (int seed);
int dado(int num_facce); // returns an integer in [0, ... , num_facce-1] uniformly at random.
#endif
Defines _RAND_H (links are to index).
<Rand.cpp>=
// File: Rand.ccp
// Last Revision: 23-Mar-2001
// Description: functions for the generation of random values.
//
// Note: The two functions myrand() and smyrand() were written by Dell'Amico
// using the portable pseudorandom generator RnG (see below).
#include "Rand.H"
#define PRANDMAX 1000000000
int dmxa, dmxb, dmxarr[55];
float myrand()
{
return ((float)lprand()) / PRANDMAX;
}
float smyrand(int seed)
{
return (float) sprand(seed);
}
int dado(int num_facce)
{
return (int) (num_facce * myrand());
}
/*
This file contains a set of c-language functions for generating
uniform integers. This is a COMPLETELY PORTABLE generator.
it will give iDEnTiCAL sequences of random numbers for any
architecture with at least 30-bit integers, regardless of the
integer representation, MAXinT value, or roundoff/truncation
method, etc.
This Truly Remarkable RnG is described more fully in
j. Bentley's column, ``The Software Exploratorium ''
to appear in Unix Review in 1991.
it is based on one in knuth, Vol 2, Section 3.2.2 (Algorithm A)
This is a little driver program so you can test the code.
Giving input parameters: 0 3 1
should produce
921674862
250065336
377506581
Giving 1000000 1 2
should produce
572653995
void main()
{
int i,j,n,m,seed;
scanf("%d %d %d",&m,&n,&seed);
i = sprand(seed);
for(i=0; i< m;i++)
j = lprand();
for (i=0; i< n; i++)
printf("\n%ld",lprand());
}
*/
// ---------RnG---------------------
// Returns long ints from the
// range 0...PRANDMAX-1
int lprand()
{
dmxa --;
if (dmxa < 0) dmxa = 54;
dmxb --;
if (dmxb < 0) dmxb = 54;
int t = dmxarr[dmxa] - dmxarr[dmxb];
return dmxarr[dmxa] = ( (t < 0) ? t + PRANDMAX : t);
}
//-----------RnG initializer------------
// Call once before using lprand
int sprand (int seed)
{
int i, ii, last, next;
dmxarr[0] = last = seed;
next = 1;
for (i=1; i< 55; i++ ) {
ii = 21 * i % 55;
dmxarr[ii] = next;
next = last - next;
if (next < 0) next += PRANDMAX;
last = dmxarr[ii];
}
dmxa = 0;
dmxb = 24;
for(i = 0; i<= 164; i++)
lprand();
return seed;
}
Defines dado, dmxa, dmxarr, dmxb, lprand, myrand, PRANDMAX, smyrand, sprand (links are to index).
<heap.H>=
#include <string.h>
template<class T> inline bool less(const T& a, const T& b) {
return (a < b);
}
inline bool less(const char* a, const char* b) {
return (strcmp(a, b) < 0 ? true : false);
}
template<class T> inline void swap(T& a, T& b) {
T temp(a);
a = b;
b = temp;
}
template<class T> class heap {
private:
size_t size;
size_t length;
T* a;
public:
heap(size_t initial_size = 10):
size(initial_size),
length(0),
a(new T[initial_size])
{ }
heap(T array[], size_t nUsed):a(array), size(sizeof(array)), length(nUsed)
{ }
virtual ~heap() {
delete[] a;
}
size_t get_used() {
return length;
}
bool is_empty() {
return (length == 0);
}
T min() {
if (is_empty()) {
throw(3);
}
return a[0];
}
void del_min() {
a[0] = a[length - 1];
--length;
movedown(0);
}
void movedown(size_t pos) {
T moving_elem = a[pos];
size_t iSon, iSonDx;
for(;;) {
iSon = (pos << 1) + 1;
if((iSonDx = iSon + 1) < length && less(a[iSonDx], a[iSon]))
++iSon;
if(iSon < length && less(a[iSon], moving_elem)) {
a[pos] = a[iSon];
pos = iSon;
}
else {
a[pos] = moving_elem;
return;
}
}
}
void insert(const T& elem) {
if (length == size) {
size_t newsize = size * 2 + 1;
T* b = new T[newsize];
memcpy((void*)a, (void*)b, sizeof(T)*size);
swap(a, b);
size = newsize;
delete[] b;
}
a[length] = elem;
moveup(length);
++length;
}
void moveup(size_t pos) {
T moving_elem = a[pos];
int father;
while((father = (int)(pos - 1) >> 1) >= 0 && less(moving_elem, a[father])) {
a[pos] = a[father];
pos = father;
}
a[pos] = moving_elem;
}
void touch(size_t pos) {
if(pos > 0 && pos < length && less(a[pos], a[(pos - 1) >> 1]))
moveup(pos);
else
movedown(pos);
}
};
<wGraph.H>=
/* File: wGraph.H
* Last Revision: 2-Apr-2001
* Description: a data type for weighted graphs.
* a weighted graph is a graph G=(V,E) with integer weights on the edges.
*
* author: Romeo Rizzi.
*
* Classes declared: wGraph
*
* The class wGraph implements:
* 1) The data structure storing a given weighted graph,
* 2) The methods for quering this data structure,
* 3) The methods to generate "DSJ_U" and "DSJ_G" graphs (see below),
* 4) The methods for loading the input graph from a file.
* (natural extension of DIMACS format, or of JOHNSON format).
*/
#ifndef _W_GRAPH_H
#define _W_GRAPH_H
#include <fstream.h>
#include <math.h>
#include "Rand.H"
#define MAX_NODES 10000
#define MAX_W 100
#define DIMACS 1
#define BINARY_DIMACS 2
#define JOHNSON 3
#define SQR(x) ( (x)*(x) )
enum graph_enum { DSJ_U, DSJ_G};
/* We generate two kinds of graphs:
* DSJ_U: Each node is put in the plane and receives two random coordinates.
* Two nodes u and v are then connected by an edge uv, if and only
* if their distance does not exceed a given constant.
* In case the edge exists, then its weight is choosen uniformly
* at random in the interval [1, ..., MAX_W].
* DSJ_G: Random weighted graphs where the probability that there exists
* an edge between any two nodes is a constant.
* In case the edge exists, then its weight is choosen uniformly
* at random in the interval [1, ..., MAX_W].
* Thus the expected degree of any vertex is a constant.
* Such graphs are indeed characterized by their expected degree.
*
* Note: G and U graphs are extensions of the unweighted graphs
* produced in the class Graph or as by Dell'Amico - Maffioli.
* Starting from a same seed we obtain the same support graph
* as in the class Graph or as Dell'Amico - Maffioli.
*/
class Graph {
/* A graph G has n nodes and m edges.
* We number the nodes of G as: 1, ... ,n.
*
* Data Structures:
*
* 1) THE ADJACENCY MATRIX: adj_M
* adj_M [u][v] == 1 if edge (u,v) exists; 0 otherwise.
*
* 2) THE MATRIX of WEIGHTS: W
* W [u][v] gives the weight of edge (u,v) when such an edge exists.
*
* 3) THE SEQUENCE OF NEIGHBORS: list_of_neighbors and first_nei
* list_of_neighbors has the following structure:
* <neighbors node 1, neighbors node 2, ... , neighbors node i, ..., neighbors node n>
* |
* first_nei[i]
*
* first_nei[i] = the position in list_of_neighbors[] of the first neighbor of vertex i
*
* The neighbors of vertex i are:
* list_of_neighbors[first_nei[i]], list_of_neighbors[first_nei[i]+1],...,list_of_neighbors[first_nei[i+1]-1]).
*
* NOTE: (a detail in our implementation of list_of_neighbors)
* Between the neighbors of node i and the neighbors
* of node (i+1) we put a 0 as separetor.
* This trick allows for a faster scan of the neighbors of any node.
* (See procedures first_neighbor(node u) and next_neighbor() below.
*/
int n_nodes; // number of nodes.
int n_edges; // number of edges.
int half_n_nodes; // half_n_nodes = (n_nodes /2).
int **adj_M;
int **W;
// SEQUENCE OF NEIGHBORS:
int *first_nei;
int *list_of_neighbors;
int *deg; // the degree array of nodes. (degree= number of neighbors).
int max_deg; // the maximum degree of a node.
int *neighbor_pos; // used to scan the neighbor of a node.
void Make_Star_DataStructure();
// derives "list_of_neighbors" and "first_nei" from "adj_M".
// ALLOCATING THE ADJACENCY MATRIX "adj_M".
void allocate_adj_M();
// ALLOCATING THE MATRIX OF WEIGHTS "W".
void allocate_W();
// STORING RANDOM WEIGHTS INTO MATRIX "W".
void random_W();
// GENERATING "DSJ_U" and "DSJ_G" GRAPHS:
int iseed; // seed to random generate graphs DSJ_U or DSJ_G.
double density, distance;
void generate_G_graph(double density);
/* Instantiates a graph of type "G".
* assumes "adj_M" having been allocated before the call.
* At termination "adj_M" is the adjacency matrix of the generated graph.
* However the star data structures are not yet initialized at termination
* and will be derived from "adj_M" in a second phase by the method "Make_Star_DataStructure()". */
void generate_U_graph(double distance);
/* Instantiates a graph of type "U".
* assumes "adj_M" having been allocated before the call.
* At termination "adj_M" is the adjacency matrix of the generated graph.
* However the star data structures are not yet initialized at termination
* and will be derived from "adj_M" in a second phase by the method "Make_Star_DataStructure()". */
// LOADING UP A GRAPH FROM A FILE:
void dimacs_input(const char *file);
// inputs a graph in the binary (compressed) dimacs format.
// see URL:
void johnson_input(const char *file);
// inputs a graph in the johnson format.
// see URL:
public:
Graph (graph_enum gen, int n, double expected_deg, int np, int seed=1);
/* Generates a graph of type <gen> with <n> nodes.
* <seed> is the seed to random generate the graph: different calls with
* the same <seed> (and the same <gen>) produce identical graphs.
* (in fact, for a given pair (<gen>, <seed>), we produce the same graph
* as Dell'Amico-Maffioli generator).
* <expected_deg> is the expected degree of the random graph to be instantiated.
* <np> is the problem number and is output after the graph
* has been generated together with other informations about the graph.
*/
Graph (const int format, const char *file);
// Creates a graph by loading it from a <file> in a given <format>.
~Graph();
void write(const int format, const char *file);
// saves the graph on a <file> according to the specifyied <format>
// (useful for conversions, of no use for the search algorithms).
int n() const // returns the number of nodes.
{ return n_nodes; }
int m() const // returns the number of edges.
{ return n_edges; }
int half_n() const // returns half the number of nodes.
{ return half_n_nodes; }
int edge(int u, int v) const // returns 1 if nodes u and v are adjacent.
{return adj_M [u][v]; } // returns 0 otherwise.
// note: edge(x,x) == 0, no self-connection.
int weight(int u, int v) const // returns the weight of edge uv.
{return W [u][v]; } // the returned value is not defined
// if u and v are not adjacent.
int max_degree() // returns the maximum degree.
{ return max_deg; }
int degree(int v) const // returns the degree of node v.
{ return deg[v]; }
int first_neighbor(int v); // returns 0 if no neighbor.
int next_neighbor(); // returns 0 if no next neighbor.
int size_of_cut(const int *x); // returns the number of edges whose
// endpoints have different x[] values.
};
inline int Graph::next_neighbor() // returns 0 if no next neighbor.
{ return *(neighbor_pos ++); }
inline int Graph::first_neighbor(int v) { // returns 0 if no neighbor.
neighbor_pos = list_of_neighbors + first_nei[v];
return next_neighbor();
}
#endif
Defines BINARY_DIMACS, DIMACS, JOHNSON, MAX_NODES, MAX_W, SQR, _W_GRAPH_H (links are to index).
<wGraph.cpp>=
/* File: wGraph.cpp
* Last Revision: 2-Apr-2001
* Description: this file contains the definition of the class wGraph
* as declared in the file wGraph.H (see file wGraph.H to get more insight).
*
* programmer: Romeo Rizzi.
*
* Classes defined: wGraph
*/
#include "wGraph.H"
#include <stdlib.h>
Graph::Graph(graph_enum gen, int num_nodi, double expected_deg,
int np, int seed)
{
n_nodes = num_nodi; n_edges = 0; half_n_nodes = num_nodi/2;
// Initialize the random generator and other parameters to generate the graph.
iseed = (long)(n_nodes *131 + expected_deg *101 + np *191 + seed ) % 32767;
smyrand(iseed);
density = (double) expected_deg / (n_nodes - 1) ;
distance = sqrt(expected_deg / (n_nodes * 3.141592653589793238));
// Allocate the adjacency matrix "adj_M [u][v]".
allocate_adj_M();
// Allocate the matrix of weights "W [u][v]".
allocate_W();
// Generate a type (gen) graph. Generate the adjacency matrix adj_M[u][v].
switch (gen) {
case DSJ_G : generate_G_graph(density);
break;
case DSJ_U : generate_U_graph(distance);
break;
}
Make_Star_DataStructure();
cout << "\n\nN= " << n_nodes << " Nu= " << expected_deg
<< " Tipo grafo= " << gen << " N.lati= " << n_edges
<< " Seed= " << iseed << " N.problema= " << np << endl;
}
void Graph::allocate_adj_M()
{
adj_M = new int*[n_nodes] -1;
for (int i = n_nodes; i; i--) {
adj_M[i] = new int[n_nodes] -1;
for(int j = n_nodes; j; j--) adj_M[i][j] = 0;
}
}
void Graph::allocate_W()
{
W = new int*[n_nodes] -1;
for (int i = n_nodes; i; i--) {
W[i] = new int[n_nodes] -1;
for(int j = n_nodes; j; j--) W[i][j] = 0;
}
}
Graph::~Graph()
{
for(int i = n_nodes; i; i--) {
delete [] (adj_M[i] +1);
delete [] (W +1);
}
delete [] (adj_M +1);
delete [] (W +1);
delete [] (first_nei +1);
delete [] (list_of_neighbors +1);
delete [] (deg +1);
}
void Graph::Make_Star_DataStructure()
{
deg = new int[n_nodes] -1; max_deg = 0;
first_nei = new int[n_nodes] -1;
list_of_neighbors = new int[2*n_edges + n_nodes] -1;
int pos = 1;
for(int i = n_nodes; i; i--) {
first_nei[i] = pos;
for(int j = n_nodes; j; j--) if (adj_M[i][j]) list_of_neighbors[ pos++ ] = j;
deg[i] = pos - first_nei[i];
list_of_neighbors[ pos++ ] = 0;
if( deg[i] > max_deg ) max_deg = deg[i];
}
}
// generate random weights and store them into matrix W
void Graph::random_W()
{
for(int i = 1; i < n_nodes; i++)
for(int j = n_nodes; j > i; j--)
if ( adj_M[i][j] )
W[i][j] = W[j][i] = 1+dado(MAX_W);
}
// generate G graphs
void Graph::generate_G_graph(double density)
{
for(int i = 1; i < n_nodes; i++)
for(int j = n_nodes; j > i; j--)
if ( myrand() < density )
{ adj_M[i][j] = adj_M[j][i] = 1; n_edges ++; }
random_W();
}
// generate U graphs
void Graph::generate_U_graph(double distance)
{
int i, j;
double *x, *y;
x = new double[n_nodes +1]; y = new double[n_nodes +1];
for(i = n_nodes; i; i--) {
x[i] = myrand();
y[i] = myrand();
}
for(i = n_nodes; i; i--)
for(j = n_nodes; j > i; j--)
if(SQR( x[i] -x[j] ) + SQR( y[i] -y[j] ) < SQR(distance))
{ adj_M[i][j] = adj_M[j][i] = 1; n_edges ++; }
delete [] x; delete [] y;
random_W();
}
void Graph::dimacs_input(const char *file)
{
ifstream in(file);
if (!in.good()) {
cerr << "err: input_graph: Input graph does not exist." << endl;
exit(1);
}
char first_char_of_line, pippo[1000];
in.get(first_char_of_line);
while(first_char_of_line != 'p') {
in.getline(pippo,1000);
in.get(first_char_of_line);
}
in >> pippo >> n_nodes >> n_edges; in.getline(pippo,1000);
// Allocate the adjacency matrix "adj_M [u][v]".
allocate_adj_M();
// Allocate the matrix of weights "W [u][v]".
allocate_W();
int i, j, w, num_arcs = n_edges;
while(num_arcs--) {
in.get(first_char_of_line);
while(first_char_of_line != 'e') {
in.getline(pippo,1000);
in.get(first_char_of_line);
}
in >> i >> j >> w; in.getline(pippo,1000);
adj_M[i][j] = 1;
adj_M[j][i] = 1;
W[i][j] = w;
W[j][i] = w;
}
half_n_nodes = n_nodes /2;
}
void Graph::johnson_input(const char *file)
{
ifstream in(file);
if (!in.good()) {
cerr << "err: input_graph: Input graph does not exist." << endl;
exit(1);
}
int max_node = 0, num_arc = 0, node_of_line, degree, neighbor, w;
char pippo[50];
do {
in >> node_of_line >> pippo >> degree;
if (node_of_line > max_node) max_node = node_of_line;
num_arc += degree;
for (; degree > 0; degree--) {
in >> neighbor;
if (neighbor > max_node) max_node = neighbor;
}
} while(in);
n_nodes = max_node; n_edges = num_arc /2;
half_n_nodes = n_nodes /2;
// Allocate the adjacency matrix "adj_M [u][v]".
allocate_adj_M();
// Allocate the matrix of weights "W [u][v]".
allocate_W();
in.close();
in.open(file);
do {
in >> node_of_line >> pippo >> degree;
for (; degree > 0; degree--) {
in >> neighbor >> w;
adj_M[node_of_line][neighbor] = 1;
adj_M[neighbor][node_of_line] = 1;
W[node_of_line][neighbor] = w;
W[neighbor][node_of_line] = w;
}
} while(in);
in.close();
}
Graph::Graph(const int format, const char *file)
{
switch (format) {
case DIMACS : dimacs_input(file); break;
case JOHNSON : johnson_input(file); break;
default:
cerr << "err: input_graph: "
<< "We input only graphs in DIMACS or JOHNSON format."
<< endl;
exit(1);
}
Make_Star_DataStructure();
}
void Graph::write(const int format, const char *file)
{
if (format != DIMACS) {
cerr << "err: output_graph: "
<< "We output only graphs in DIMACS format." << endl;
exit(1);
}
ofstream output(file);
output << "p gp " << n_nodes << " " << n_edges << endl;
for(int i = 1; i < n_nodes; i++)
for(int j = i+1; j <= n_nodes; j++)
if (adj_M[i][j]) output << "e " << i << " " << j
<< " " << W[i][j] << endl;
output.close();
}
int Graph::size_of_cut(const int *x) // returns the number of edges whose
// endpoints have different x[] values.
{
int size = 0;
for(int node = n_nodes; node; node--) {
int x_node = x[node];
neighbor_pos = list_of_neighbors + first_nei[node];
while(*neighbor_pos > node)
if(x[*(neighbor_pos ++)] != x_node)
++size;
}
return size;
}
Defines Graph (links are to index).
<kruskal.cpp>=
#include <iostream.h>
#include "wGraph.H"
#include "heap.H" // lo heap di Lorenzo Dematte
void usageSyntaxHelp(int argc, char **argv);
struct elem {
int father;
int card;
};
class setUnion {
int n; // cardinality of the ground set.
elem * eqClass;
public:
setUnion(int n) {
eqClass = new elem[n+1];
for(int i = 1; i <= n; i++) {
eqClass[i].father = i;
eqClass[i].card = 1;
}
}
~setUnion() { delete eqClass; }
void Union(int i, int j) {
if(eqClass[j].card < eqClass[i].card) {
int swap = i;
i = j;
j = swap;
}
eqClass[i].father = j;
eqClass[j].card = eqClass [j].card + eqClass [i].card ;
eqClass[i].card = 0;
}
int find(int i) {
while(eqClass[i].card == 0) i = eqClass[i].father;
return i;
}
};
struct edge {
public:
int node_A;
int node_B;
int weight;
};
inline bool less(const edge a, const edge b) {
return (a.weight < b.weight);
}
int main(int argc, char **argv) {
usageSyntaxHelp(argc, argv);
Graph* G = new Graph(DIMACS, argv[1]);
heap<edge> HeapOfEdges;
for(int v = G->n(); v; v--)
for(int nei = G->first_neighbor(v);
nei; nei = G->next_neighbor())
if(nei > v) {
edge e;
e.node_A = v;
e.node_B = nei;
e.weight = G->weight(v,nei);
HeapOfEdges.insert(e);
}
setUnion components(G->n());
int cost = 0;
while (!HeapOfEdges.is_empty()) {
edge e = HeapOfEdges.min();
HeapOfEdges.del_min();
int component_A = components.find(e.node_A);
int component_B = components.find(e.node_B);
if(component_A != component_B) {
cost += e.weight;
cout << "arco (" << e.node_A << "," << e.node_B << ")" << endl;
components.Union(component_A, component_B);
}
}
delete G;
exit(0);
}
void usageSyntaxHelp(int argc, char **argv) {
if(argc != 2) {
exit(1);
}
}
Defines main, usageSyntaxHelp (links are to index).
- BINARY_DIMACS: D1
- dado: U1, D2, U3
- DIMACS: D1, U2, U3
- dmxa: D1
- dmxarr: D1
- dmxb: D1
- Graph: U1, D2, U3
- JOHNSON: D1, U2
- lprand: U1, D2
- main: U1, D2
- MAX_NODES: D1
- MAX_W: D1, U2
- myrand: U1, D2, U3
- PRANDMAX: D1
- _RAND_H: D1
- smyrand: U1, D2, U3
- sprand: U1, D2
- SQR: D1, U2
- usageSyntaxHelp: D1
- _W_GRAPH_H: D1