/**
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
* .
*
* (c) Vincenzo Nicosia 2009-2017 --
*
* This file is part of NetBunch, a package for complex network
* analysis and modelling. For more information please visit:
*
* http://www.complex-networks.net/
*
* If you use this software, please add a reference to
*
* V. Latora, V. Nicosia, G. Russo
* "Complex Networks: Principles, Methods and Applications"
* Cambridge University Press (2017)
* ISBN: 9781107103184
*
***********************************************************************
*
* This program finds the minimum/maximum spanning tree of a graph
* given as input, using the Kruskal's algorithm
*
*
* References:
*
* [1] J. B. Kruskal. "On the shortest spanning subtree of a graph and
* the traveling sales-man problem". P. Am. Math. Soc. 7 (1956),
* 48-48.
*
*/
#include
#include
#include
#include "dset.h"
#include "gen_heap.h"
#include "utils.h"
#include "edge_w_funs.h"
void usage(int argc, char *argv[]){
printf("********************************************************************\n"
"** **\n"
"** -*- kruskal -*- **\n"
"** **\n"
"** Find the minimum/maximum spanning tree of a weighted graph **\n"
"** 'graph_in' provided as input. **\n"
"** **\n"
"** The input file 'graph_in' is a weighted edge-list: **\n"
"** **\n"
"** I_1 J_1 W_1 **\n"
"** I_2 J_2 W_2 **\n"
"** I_3 J_3 W_3 **\n"
"** ... ... **\n"
"** I_K J_K W_K **\n"
"** **\n"
"** The program computes by default the minimum spanning tree **\n"
"** of 'graph_in', unless the second parameter 'MAX' is **\n"
"** specified. **\n"
"** **\n"
"** The program prints on STDOUT the weighted edge-list of the **\n"
"** minimum/maximum spanning tree of 'graph_in'. **\n"
"** **\n"
"** If 'graph_in' is an unweighted graph, the program prints **\n"
"** on output one of the spanning trees of the graph. **\n"
"** **\n"
"********************************************************************\n"
" This is Free Software - You can use and distribute it under \n"
" the terms of the GNU General Public License, version 3 or later\n\n"
" Please visit http://www.complex-networks.net for more information\n\n"
" (c) Vincenzo Nicosia 2009-2017 (v.nicosia@qmul.ac.uk)\n"
"********************************************************************\n\n"
);
printf("Usage: %s [MAX]\n", argv[0]);
}
void kruskal(gen_heap_t *h, unsigned int N){
dset_t *nodes, set1, set2;
edge_w_t *elem;
unsigned int i;
nodes = malloc(N * sizeof(dset_t));
for(i=0; ii]);
set2 = dset_find(nodes[elem->j]);
/* if i and j do not belong to the same disjoint set...*/
if (set1 != set2){
/* ... the edge (i,j) belongs to the spanning tree, */
/* so we print it...*/
print_elem_edge_w(elem);
/* ...then merge the two sets... */
dset_union(nodes[elem->i], nodes[elem->j]);
}
free(elem);
}
/* We now destroy all the disjoint sets... */
for (i=0;ii = atoi(ptr);
ptr = strtok(NULL, " "); /* read the second node */
VALID_PTR_OR_EXIT(ptr, 7);
elem->j = atoi(ptr);
ptr = strtok(NULL, " "); /* read the weight */
if (!ptr)
/* if no weight is specified, assume it is set to 1.0 */
elem->w = 1.0;
else
elem->w = atof(ptr);
/* put the edge in the heap */
gen_heap_insert(h, elem);
}
}
int count_num_lines(FILE *filein){
int i, ch ;
i = 0;
while ((ch = fgetc(filein)) != EOF){
if (ch == '\n')
i ++;
}
rewind(filein);
return i;
}
int main(int argc, char *argv[]){
gen_heap_t *h;
unsigned int N;
FILE *filein;
char htype;
gen_heap_func_t *funs;
if(argc < 2){
usage(argc, argv);
exit(1);
}
htype = MIN_HEAP;
if (argc > 2 && !my_strcasecmp(argv[2], "MAX")){
htype = MAX_HEAP;
}
/* Initialisation of functions for gen_heap*/
funs = malloc(sizeof(gen_heap_func_t));
(*funs).compare = compare_edge_w;
(*funs).alloc_vector = alloc_vector_edge_w;
(*funs).dealloc_vector = dealloc_vector_edge_w;
(*funs).dealloc_elem = dealloc_elem_edge_w;
(*funs).print_elem = print_elem_edge_w;
filein = openfile_or_exit(argv[1], "r", 2);
N = count_num_lines(filein);
h = gen_heap_init(N, htype, funs);
load_edges_into_heap(filein, h);
fclose(filein);
kruskal(h, N);
gen_heap_destroy(h);
free(funs);
}