Cod sursa(job #1536411)

Utilizator rockerboyHutter Vince rockerboy Data 26 noiembrie 2015 08:27:38
Problema Algoritmul lui Dijkstra Scor 30
Compilator cpp Status done
Runda Arhiva educationala Marime 3.72 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <climits>
#include <cstdlib>

#define NODE(n) (n>>10)
#define COST(n) (n&1023)

class tipus
{
    int sorszam, kulcs;

public:
    tipus (int s, int k): sorszam(s), kulcs(k) {}
    inline int key() {return kulcs;}
    inline int num() {return sorszam;}
    inline void set_key (int k) {kulcs = k;}
};

template <typename elem_t>
class heap
{
    std::vector<int> pos;
    std::vector<elem_t> x;

    bool leaf (unsigned p)
    {
        if (p <= (x.size()-1)/2) return false;
        return true;
    }

    void upheap (unsigned currentpos)
    {
        while (x[currentpos].key() < x[currentpos/2].key()) {
            std::swap (x[currentpos], x[currentpos/2]);
            pos[currentpos] = currentpos/2;
            pos[currentpos/2] = currentpos;
            currentpos /= 2;
        }
    }

    void downheap (unsigned currentpos)
    {
        unsigned minpos;
        int k1, k2;

        while (not leaf (currentpos) && currentpos != 0) {
            if (currentpos*2 == x.size()-1) {
                if (x[currentpos].key() > x[currentpos*2].key()) {
                    std::swap (x[currentpos], x[currentpos*2]);
                    pos[currentpos] = currentpos*2;
                    pos[currentpos*2] = currentpos;
                    currentpos *= 2;
                }
                continue;
            }
            k1 = x[currentpos*2].key();
            k2 = x[currentpos*2+1].key();
            minpos = k1;
            if (k2 < k1) minpos = k2;
            if (x[minpos].key() < x[currentpos].key()) {
                std::swap (x[minpos], x[currentpos]);
                pos[currentpos] = minpos;
                pos[minpos] = currentpos;
                currentpos = minpos;
            }
        }
    }

public:
    heap (unsigned n): pos(n, -1) {}
    ~heap () {pos.clear(); x.clear();}

    void push (elem_t elem)
    {
        x.push_back (elem);
        unsigned currentpos = x.size()-1;
        pos[elem.num()] = currentpos;
        upheap (currentpos);
    }

    int min ()
    {
        return x[0].num();
    }

    unsigned size ()
    {
        return x.size();
    }

    bool exists (unsigned p)
    {
        if (pos[p] == -1) return false;
        return true;
    }

    void pop ()
    {
        pos[x[0].num()] = -1;
        x[0] = x.back();
        pos[x[0].num()] = 0;
        x.pop_back();
        downheap (0);
    }

    void decrease_key (int node, int val)
    {
        x[pos[node]].set_key(val);
        upheap (val);
    }
};

std::ifstream in ("dijkstra.in");
std::ofstream out ("dijkstra.out");

int n, m;
std::vector< std::list<int> > x;
std::vector<int> path;

void dijkstra (int node)
{
    path[node] = 0;
    heap<tipus> Min (n+1);
    Min.push (tipus(node, 0));

    int pos, newlen;
    std::list<int>::iterator i;
    while (Min.size()) {
        pos = Min.min();
        Min.pop();
        for (i=x[pos].begin(); i!=x[pos].end(); i++) {
            newlen = path[pos] + COST(*i);
            if (newlen < path[NODE(*i)]) {
                path[NODE(*i)] = newlen;
                if (Min.exists(NODE(*i))) Min.decrease_key (NODE(*i), newlen);
                else Min.push (tipus(NODE(*i), newlen));
            }
        }
    }
}


int main()
{
    in >> n >> m;
    x.resize (n+1);
    path.resize (n+1, INT_MAX);

    int a, b, c, i;
    for (i=0; i<m; i++) {
        in >> a >> b >> c;
        x[a].push_back ((b << 10) + c);
    }

    dijkstra (1);

    for (i=2; i<=n; i++) {
        if (path[i] != INT_MAX) out << path[i] << " ";
        else out << "0 ";
    }

    exit (0);
}