Cod sursa(job #1193784)

Utilizator a.stanciuStanciu Adrian a.stanciu Data 1 iunie 2014 19:16:47
Problema Algoritmul lui Dijkstra Scor 20
Compilator c Status done
Runda Arhiva educationala Marime 4.23 kb
#include <stdio.h>
#include <stdlib.h>

#define INF 4294967295

struct node {
	int v;
	int cost;
	struct node *next;
};

struct min_heap {
	int key;
	int val;
};

void print_min_heap(struct min_heap *min_heap, int *index, int n)
{
	int i;
	for (i = 1; i <= n; i++)
		printf("(%d,%d) ", min_heap[i].key, min_heap[i].val);
	printf("\n");
	for (i = 1; i <= n; i++)
		printf("%d, ", index[i]);
	printf("\n");
}

void heap_swap(struct min_heap *min_heap, int *index, int i, int j)
{
	if (i == j)
		return;

	int u = min_heap[i].val;
	int v = min_heap[j].val;

	struct min_heap aux = min_heap[i];
	min_heap[i] = min_heap[j];
	min_heap[j] = aux;

	int tmp = index[u];
	index[u] = index[v];
	index[v] = tmp;
}

void bubble_up(struct min_heap *min_heap, int *index, int heap_size)
{
	if (heap_size == 1)
		return;

	unsigned int key = min_heap[heap_size].key;
	int vertex = min_heap[heap_size].val;

	int parent = heap_size / 2;
	unsigned int parent_key = min_heap[parent].key;

	while (key < parent_key) {
		heap_swap(min_heap, index, heap_size, parent);
		parent = index[vertex] / 2;
		parent_key = min_heap[parent].key;
	}
}

void heap_insert(struct min_heap *min_heap, unsigned int key, int *index, int vertex, int *heap_size)
{
	(*heap_size)++;

	min_heap[*heap_size].key = key;
	min_heap[*heap_size].val = vertex;
	index[vertex] = *heap_size;
	bubble_up(min_heap, index, *heap_size);
}

void bubble_down(struct min_heap *min_heap, int *index, int heap_size, int i)
{
	if (heap_size <= 1)
		return;

	unsigned int key = min_heap[i].key;

	unsigned int child1_key = INF;
	unsigned int child2_key = INF;

	if (2 * i <= heap_size)
		child1_key = min_heap[2 * i].key;
	if (2 * i + 1 <= heap_size)
		child2_key = min_heap[2 * i + 1].key;

	if (key > child1_key || key > child2_key) {
		int min_child = (child1_key < child2_key) ? 2 * i : 2 * i + 1;

		heap_swap(min_heap, index, min_child, i);
		bubble_down(min_heap, index, heap_size, min_child);
	}
}

struct min_heap heap_extract_min(struct min_heap *min_heap, int *index, int *heap_size)
{
	struct min_heap min = min_heap[1];

	heap_swap(min_heap, index, 1, *heap_size);
	(*heap_size)--;

	bubble_down(min_heap, index, *heap_size, 1);

	return min;
}

void heap_replace(struct min_heap *min_heap, unsigned int key, int *index, int vertex)
{
	int i = index[vertex];

	if (key < min_heap[i].key) {
		min_heap[i].key = key;

		bubble_up(min_heap, index, i);
	}
}

void dijkstra(struct node **nodes, int n, int start)
{
	struct min_heap *min_heap = calloc(n + 1, sizeof(struct min_heap));
	int heap_size = 0;
	int *index = malloc((n + 1) * sizeof(int));
	unsigned int *dist = malloc((n + 1) * sizeof(unsigned int));

	int i;
	for (i = 1; i <= n; i++) {
		index[i] = -1;
		dist[i] = INF;
	}

	dist[start] = 0;
	struct node *vertex = nodes[start];
	while (vertex) {
		heap_insert(min_heap, dist[start] + vertex->cost, index, vertex->v, &heap_size);
		vertex = vertex->next;
	}

	//print_min_heap(min_heap, index, n);

	for (i = 1; i < n; i++) {
		struct min_heap min = heap_extract_min(min_heap, index, &heap_size);

		dist[min.val] = min.key;

		struct node *vertex = nodes[min.val];
		while (vertex) {
			if (dist[vertex->v] == INF) {
				if (index[vertex->v] == -1)
					heap_insert(min_heap, dist[min.val] + vertex->cost, index, vertex->v, &heap_size);
				else
					heap_replace(min_heap, dist[min.val] + vertex->cost, index, vertex->v);
			}
			vertex = vertex->next;
		}
	}

	FILE *f = fopen("dijkstra.out", "w");
	for (i = 2; i <= n; i++)
		if (dist[i] == INF)
			fprintf(f, "0 ");
		else
			fprintf(f, "%u ", dist[i]);
	fclose(f);
}

int main()
{
	FILE *f = fopen("dijkstra.in", "r");

	int n, m, start = 1;
	//fscanf(f, "%d %d %d", &n, &m, &start);
	fscanf(f, "%d %d", &n, &m);

	struct node **nodes = calloc(n + 1, sizeof(struct node *));

	int i;
	for (i = 0; i < m; i++) {
		int u, v, cost;
		fscanf(f, "%d %d %d", &u, &v, &cost);

		struct node *vertex = calloc(1, sizeof(struct node));
		vertex->v = v;
		vertex->cost = cost;

		if (!nodes[u])
			nodes[u] = vertex;
		else {
			vertex->next = nodes[u];
			nodes[u] = vertex;
		}
	}

	fclose(f);
/*
	for (i = 1; i <= n; i++) {
		printf("%d: ", i);
		struct node *vertex = nodes[i];
		while (vertex) {
			printf("%d, ", vertex->v);
			vertex = vertex->next;
		}
		printf("\n");
	}
*/

	dijkstra(nodes, n, start);

	return 0;
}