Cod sursa(job #1728074)

Utilizator preda.andreiPreda Andrei preda.andrei Data 12 iulie 2016 11:18:45
Problema Drumuri minime Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.82 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#include <set>
#include <cmath>

using namespace std;

#define NMAX 1501
#define NUMAR_MODULO 104659
#define INFINIT 0x3F3F3F3F
#define EPSILON 0.001

struct Nod
{
    vector< pair<int, double> > vecini;
    set<int> predecesori;
    int drumuriMinime;
    int costMinim;
    bool inCoada;
};

Nod noduri[NMAX];

void aflaCosturi(int start);
void aflaDrumuri(int start);
bool cmpNoduri(int n1, int n2);

int main()
{
    ifstream fin("dmin.in");
    ofstream fout("dmin.out");

    int n, m;
    fin >> n >> m;

    for (int i = 1; i <= n; ++i) {
        noduri[i].costMinim = INFINIT;
    }

    while (m--) {
        int x, y;
        double c;
        fin >> x >> y >> c;
        c = log(c);

        noduri[x].vecini.push_back(make_pair(y, c));
        noduri[y].vecini.push_back(make_pair(x, c));
    }

    aflaCosturi(1);

    aflaDrumuri(1);

    for (int i = 2; i <= n; ++i) {
        fout << noduri[i].drumuriMinime << " ";
    }

    return 0;
}

void aflaDrumuri(int start)
{
    queue<int> q;
    q.push(start);

    noduri[start].drumuriMinime = 1;
    noduri[start].inCoada = true;

    while (!q.empty()) {
        int curent = q.front();
        q.pop();

        for (int predecesor : noduri[curent].predecesori) {
            noduri[curent].drumuriMinime += noduri[predecesor].drumuriMinime;
            noduri[curent].drumuriMinime %= NUMAR_MODULO;
        }

        for (auto muchie : noduri[curent].vecini) {
            int vecin = muchie.first;
            if (!noduri[vecin].inCoada) {
                q.push(vecin);
                noduri[vecin].inCoada = true;
            }
        }
    }
}

void aflaCosturi(int start)
{
    priority_queue<int, vector<int>, decltype(&cmpNoduri)> q(&cmpNoduri);
    q.push(start);

    noduri[start].costMinim = 1;

    while (!q.empty()) {
        int curent = q.top();
        q.pop();

        noduri[curent].inCoada = false;

        for (auto muchie : noduri[curent].vecini) {
            int vecin = muchie.first;
            int costNou = noduri[curent].costMinim * muchie.second;

            if (costNou < noduri[vecin].costMinim) {
                noduri[vecin].costMinim = costNou;
                noduri[vecin].predecesori.clear();
                noduri[vecin].predecesori.insert(curent);

                if (!noduri[vecin].inCoada) {
                    q.push(vecin);
                    noduri[vecin].inCoada = true;
                }
            }
            else if (abs(costNou - noduri[vecin].costMinim) <= EPSILON) {
                noduri[vecin].predecesori.insert(curent);
            }
        }
    }
}

bool cmpNoduri(int n1, int n2)
{
    return noduri[n1].costMinim > noduri[n2].costMinim;
}