Cod sursa(job #841783)

Utilizator Brz_VladBrezae Vlad Brz_Vlad Data 24 decembrie 2012 21:40:44
Problema Algoritmul lui Dijkstra Scor 100
Compilator c Status done
Runda Arhiva educationala Marime 3.84 kb
#include <stdio.h>
#include <stdlib.h>

///////////////////LISTA/////////////////////////

typedef struct tagNode
{
	int vecin;
	int cost;
	struct tagNode *next;
}Node;

typedef struct tagList
{
	Node* start;
}List;

void initList(List *list)
{
	list->start = NULL;	
}

void addList(List *list, int vecin, int cost)
{
    Node *new = malloc(sizeof(Node));
    new->next = list->start;
    new->vecin = vecin;
    new->cost = cost;
    list->start = new;
}

void printList(List *list)
{
	Node *q = list->start;
	printf("LIST :");
	while( q != NULL ){
		printf(" (%d,%d)",q->vecin, q->cost);
		q = q->next;
	}
	printf("\n");
}

/////////////////////////////////////////////////

#define MAXN 50002

enum Type { WHITE=0, GREY, BLACK };

int N,M;
enum Type node_status[MAXN];
int distance[MAXN];

List vecini[MAXN];

//////////////////// HEAP /////////////////////////

typedef struct tagHeapNode{
	int node;
	int distance;
}HeapNode;


struct Heap{
	HeapNode nodes[MAXN];
	int heap_position[MAXN];
	int count;	
};

struct Heap heap;

void swapInt(int* a, int* b)
{
	int aux;
	aux = *a;
	*a = *b;
	*b = aux;
}

void swapHeapNode(HeapNode *a, HeapNode *b)
{
	HeapNode aux;
	aux = *a;
	*a = *b;
	*b = aux;
	
	swapInt( &heap.heap_position[a->node], &heap.heap_position[b->node] );
}

struct Heap heap;

void HeapUp(int node)
{
	while( node != 1 && heap.nodes[node/2].distance > heap.nodes[node].distance ){
		swapHeapNode(&heap.nodes[node/2], &heap.nodes[node]);
		node = node/2;
	}
}

// se presupune ca nu exista in heap
void HeapAdd(int node, int distance)
{
	HeapNode new;
	new.node = node;
	new.distance = distance;
	
	heap.count++;
	heap.nodes[heap.count] = new;
	heap.heap_position[node] = heap.count;
	
//	printf("HeapAdd %d d=%d, count = %d\n",node,distance,heap.count);
	HeapUp(heap.count);	
}

HeapNode HeapPop()
{
	HeapNode ret = heap.nodes[1];
	heap.heap_position[ret.node] = 0;
	heap.nodes[1] = heap.nodes[heap.count];
	heap.heap_position[heap.nodes[1].node] = 1;
	heap.count--;
	
	int node = 1;
	while(1){
		int st,dr,min;
		st = node*2;
		dr = node*2 + 1;
		min = node;
		
		if( st <= heap.count && heap.nodes[min].distance > heap.nodes[st].distance )
			min = st;
		if( dr <= heap.count && heap.nodes[min].distance > heap.nodes[dr].distance )
			min = dr;
			
		if( min == node )
			break;
		else{
			swapHeapNode(&heap.nodes[min], &heap.nodes[node]);
			node = min;			
		}
	}
	
	return ret;
}

void printHeap()
{
	int j;
	for(j=1;j<=heap.count;j++)
		printf("(%4d,%4d,%3d) ",heap.nodes[j].node, heap.nodes[j].distance, heap.heap_position[heap.nodes[j].node]);
	printf("\n\n");
	
}


///////////////////////////////////////////////////

int main(int argc, char* argv[])
{
	freopen("dijkstra.in","r",stdin);
	freopen("dijkstra.out","w",stdout);
	
	scanf("%d %d",&N,&M);
	int i,a,b,c;
	for(i=1;i<=N;i++)
		initList(&vecini[i]);
	for(i=0;i<M;i++){
		scanf("%d %d %d",&a,&b,&c);
		addList(&vecini[a],b,c);
	}

	node_status[1] = BLACK;
	HeapAdd(1,0);
	
	while( heap.count != 0 ){
		HeapNode current = HeapPop();
		distance[current.node] = current.distance;
		node_status[current.node] = BLACK;
		
//		printf("Am scos de pe heap nodul %d cu d=%d\n",current.node,current.distance);
//		printHeap();
		
		Node* q = vecini[current.node].start;
		while( q != NULL ){
			if(  node_status[q->vecin] == GREY ){
				int pos = heap.heap_position[q->vecin];
				if( heap.nodes[pos].distance > ( current.distance + q->cost ) ){
//					printf("Update la heap la nodul %d cu distanta de la %d la %d\n",q->vecin,heap.nodes[pos].distance, current.distance + q->cost);
					heap.nodes[pos].distance = current.distance + q->cost;
					HeapUp(pos);
//					printHeap();
				}
			}
			else if( node_status[q->vecin] == WHITE ){
				node_status[q->vecin] = GREY;
				HeapAdd(q->vecin, current.distance + q->cost);
//				printHeap();		
			}
			// BLACK jet
			q = q->next;
		}		
	}
	
	for(i=2;i<=N;i++){
		printf("%d ",distance[i]);
	}
	
	return 0;
}