From e697468d7903546b6b3e48c011feeacbd55cf8df Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ladislav=20L=C3=A1ska?= <krakonos@krakonos.org>
Date: Mon, 4 May 2015 09:30:00 +0200
Subject: [PATCH] aim-comp - hledani komponent grafu

---
 aim-comp/Makefile     |  14 ++++++
 aim-comp/comp.c       | 112 ++++++++++++++++++++++++++++++++++++++++++
 aim-comp/makegraph.pl |  28 +++++++++++
 3 files changed, 154 insertions(+)
 create mode 100644 aim-comp/Makefile
 create mode 100644 aim-comp/comp.c
 create mode 100755 aim-comp/makegraph.pl

diff --git a/aim-comp/Makefile b/aim-comp/Makefile
new file mode 100644
index 0000000..4b69909
--- /dev/null
+++ b/aim-comp/Makefile
@@ -0,0 +1,14 @@
+all:
+	gcc -o comp -g -std=c11 -Wall -Wextra comp.c
+
+clean:
+	rm -f comp
+
+samples:
+	./makegraph.pl 100 1 > small.g
+
+samples-evil:
+	./makegraph.pl 10000000 1 > big.g
+	./makegraph.pl 10000000 2 > extra.g
+
+.PHONY: all clean
diff --git a/aim-comp/comp.c b/aim-comp/comp.c
new file mode 100644
index 0000000..49c6a9e
--- /dev/null
+++ b/aim-comp/comp.c
@@ -0,0 +1,112 @@
+/******************************************************************************
+ * Filename: comp.c
+ *
+ * Created: 2015/04/26 20:56
+ * Author: Ladislav Láska
+ * e-mail: laska@kam.mff.cuni.cz
+ *
+ ******************************************************************************/
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+struct vertex {
+	struct vertex **neighbours;
+	int comp;
+};
+
+struct graph {
+	int n;
+	struct vertex* vertices;
+};
+
+
+struct graph * graph_load( char *file ) {
+	FILE *f = fopen(file, "r");
+	if (!f) {
+		printf("Could not read input file.\n");
+		goto fail;
+	}
+	struct graph *g = calloc(1, sizeof(struct graph));
+	
+	/* First line contains number of vertices. */
+	if (1 != fscanf(f, "%i\n", &g->n)) {
+		fprintf(stderr, "Format error: Invalid header.\n");
+		goto fail;
+	}
+	g->vertices = calloc(g->n, sizeof(struct vertex));
+	/* Other lines contain it's number, neighbour count and their numbers. */
+	for (int i = 0; i < g->n; i++) {
+		int id, neighbours;
+		if (2 != fscanf(f, "%i %i", &id, &neighbours)) {
+			fprintf(stderr, "Format error: Invalid line %i.\n", i);
+			goto fail;
+		}
+		if (id == g->n) {
+			fprintf(stderr, "Found vertex #%i, but only %i vertices expected!\n", id, g->n);
+			goto fail;
+		}
+		g->vertices[id].neighbours = calloc(neighbours+1, sizeof(struct vertex*));
+		for (int j = 0; j < neighbours; j++) {
+			int vref;
+			if (1 != fscanf(f, "%i", &vref)) {
+				fprintf(stderr, "Format error: Invalid edge %i at vertex %i.\n", j, i);
+				goto fail;
+			}
+			if (vref >= g->n) {
+				fprintf(stderr, "Format error: Invalid reference to nonexistent vertex %i.\n", vref);
+				goto fail;
+			}
+			g->vertices[id].neighbours[j] = &g->vertices[vref];
+			assert(g->vertices[id].neighbours[j+1] == NULL);
+		}
+	}
+	fclose(f);
+	return g;
+	fail:
+	if (g) {
+		if (g->vertices) {
+			for (int i = 0; i < g->n; i++) {
+				if (g->vertices[i].neighbours)
+					free(g->vertices[i].neighbours);
+			}
+			free(g->vertices);
+		}
+		free(g);
+	}
+	return NULL;
+}
+
+void mark_component(struct vertex *v, int comp) {
+	assert(v);
+	v->comp = comp;
+	for (int i = 0; v->neighbours[i] != NULL; i++) {
+		if (v->neighbours[i]->comp) continue;
+		mark_component(v->neighbours[i], comp);
+	}
+}
+
+int find_components(struct graph *g) {
+	int comp = 0;
+	for (int i = 0; i < g->n; i++) {
+		if (g->vertices[i].comp) continue;
+		comp++;
+		mark_component(&g->vertices[i], comp);
+	}
+	return comp;
+}
+
+int main(int argc, char **argv) {
+	if (argc != 2) {
+		fprintf(stderr, "Usage: ./comp graph_file.g");
+		exit(1);
+	}
+	struct graph *g = graph_load(argv[1]);
+	if (g) {
+		fprintf(stderr, "Processing graph '%s' on %i vertices.\n", argv[1], g->n);
+		printf("Found %i components.\n", find_components(g));
+	}
+	return 0;
+}
diff --git a/aim-comp/makegraph.pl b/aim-comp/makegraph.pl
new file mode 100755
index 0000000..b3e20b0
--- /dev/null
+++ b/aim-comp/makegraph.pl
@@ -0,0 +1,28 @@
+#!/usr/bin/perl
+
+use common::sense;
+use Data::Dumper;
+use List::Util qw(reduce);
+
+my ($nodes, $adeg) = @ARGV;
+
+die "Usage: ./makegraph.pl num_nodes avg_deg." unless defined $nodes && defined $adeg;
+
+srand(42);
+
+my @graph;
+
+my $th = $nodes/$adeg;
+
+for (my $i = 0; $i < $nodes; $i++) {
+	for (my $j = int(rand($th)); $j < $nodes; $j += 1+int(rand($th))) {
+		$graph[$i]->{$j} = 1;
+		$graph[$j]->{$i} = 1;
+	}
+}
+
+print "$nodes\n";
+for (my $i = 0; $i < $nodes; $i++) {
+	my $sum = scalar keys %{$graph[$i]};
+	print "$i $sum ".join(" ", keys %{$graph[$i]})."\n";
+}
-- 
GitLab