Cod sursa(job #623062)

Utilizator sebii_cSebastian Claici sebii_c Data 18 octombrie 2011 23:18:38
Problema Algoritmul lui Dijkstra Scor 0
Compilator c Status done
Runda Arhiva educationala Marime 2.49 kb
#include <stdio.h>
#include <stdlib.h>
#define VMAX 36005
#define INF (1<<30)

struct graf {
    long cost;
    int node;
    struct graf *next;
};

struct graf *A[VMAX];
int viz[VMAX], source[VMAX];
long dist[VMAX];
int rez[VMAX], poz[VMAX], h[VMAX];
int N, M, K, size;

inline long minimum(long x, long y)
{
    return (x<y)?x:y;
}

void swap(int prev, int now)
{
    int aux = h[prev];
    h[prev] = h[now];
    h[now] = aux;
}

void heapUp(int what)
{
    int f;
    while (what > 1) {
        f = what >> 1;
        if (dist[h[f]] > dist[h[what]]) {
	poz[h[f]] = what;
	poz[h[what]] = f;
	swap(what, f);
	what = f;
        }
        else
	what = 1;
    }       
}

void heapDown(int what)
{
    int f;
    while (what <= size) {
        f = what;
        if ((what << 1) <= size) { 
	f = what<<1;
	if (f+1 <= size)
	    if (dist[h[f+1]] < dist[h[f]])
	        ++f;
        }
        else
	return;
        if (dist[h[what]] > dist[h[f]]) {
	poz[h[what]] = f;
	poz[h[f]] = what;
	swap(what, f);
	what = f;
        }
        else
	return;
    }
}

void add(int what, int where, long cost)
{
    struct graf *q = malloc(sizeof(struct graf));
    q->node = what;
    q->cost = cost;
    q->next = A[where];
    A[where] = q;
}

void read()
{
    int x, y, i;
    long cost;
    scanf("%d %d %d", &N, &M, &K);
    for (i=1; i<=N; ++i) {
        dist[i] = INF;
        poz[i] = -1;
    }
    for (i=1; i<=K; ++i) {
        scanf("%d", &source[i]);
        rez[source[i]] = source[i];
        dist[source[i]] = 0;
        h[++size] = source[i];
        poz[h[size]] = i;
    }
    for (i=1; i<=M; ++i) {
        scanf("%d %d %ld", &x, &y, &cost);
        add(x, y, cost);
        add(y, x, cost);
    }
}

void Dijsktra()
{
    int min;
    struct graf *q;

    while (size) {
	min = h[1];
	swap(1, size);
	poz[h[1]] = 1;
	--size;
	heapDown(1);
           
	q = A[min];
	while (q) {
	    if (dist[q->node] == dist[min] + q->cost)
	      rez[q->node] = minimum(rez[q->node], rez[min]);
	    if (dist[q->node] > dist[min] + q->cost) {
	        dist[q->node] = dist[min] + q->cost;
	        rez[q->node] = rez[min];
	        if (poz[q->node] != -1)
		heapUp(poz[q->node]);
	        else {
		h[++size] = q->node;
		poz[h[size]] = size;
		heapUp(size);
	        }
	    }
	    q = q->next;
	}
    }
}

int main()
{
    int i;
    freopen("catun.in", "r", stdin);
    freopen("catun.out", "w", stdout);
    
    read();
    Dijsktra();
    for (i=1; i<=K; ++i)
        rez[source[i]] = 0;
    for (i=1; i<=N; ++i)
        printf("%d ", rez[i]);
    return 0;
}