Cod sursa(job #1606057)

Utilizator mariapascuMaria Pascu mariapascu Data 19 februarie 2016 19:52:27
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.41 kb
#include <fstream>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

struct Pair {
    int dist, nod;
    bool operator < (const Pair& P) const {
        return dist > P.dist;
    }
};

using VI = vector<int>;
using VVI = vector<VI>;
using PII = pair<int, int>;

const int INF = 0x3f3f3f3f;
int N, M, K;
vector<vector<PII>> G; //graful
VI C, d; // C - orasele speciale; d - Dijkstra din sursa;
VVI D, dp; // D[i][j] - dist min de la c[i] la nodul j; dp - dist min din 1 pana la c[j], daca drumul contine
                                                            //o submultime i de noduri din cele speciale si j e inclus in i

void Read();
void Dijkstra(int S, VI& d);

int main() {
    Read();
    Dijkstra(1, d);
    if (K == 0) {
        fout << d[N];
        fin.close();
        fout.close();
        return 0;
    }
    for (int i = 0; i < K; i++)
        Dijkstra(C[i], D[i]);
    //initializare
    for (int i = 0; i < K; i++)
        dp[1 << i][i] = d[C[i]];
    //dinamica
    for (int i = 1; i < (1 << K); i++) //pt fiecare submultime i de pozitii din sirul C
        for (int j = 0; j < K; j++)
            if (i & (1 << j))
                for (int k = 0; k < K; k++)
                    if (!(i && (1 << k)))
                        dp[i | (1 << k)][k] = min(dp[i | (1 << k)][k], dp[i][j] + D[j][C[k]]);
    int res = INF;
    for (int i = 0; i < K; i++)
        res = min(res, dp[(1 << K) - 1][i] + D[i][N]);
    fout << res;
    fin.close();
    fout.close();
    return 0;
}

void Dijkstra(int S, VI& d) {
    priority_queue<Pair> Q;
    d = VI(N + 1, INF);
    d[S] = 0; Q.push({0, S});
    int x, dx, y ,w;
    while (!Q.empty()) {
        x = Q.top().nod; dx = Q.top().dist; Q.pop();
        if (dx > d[x]) continue;
        for (const auto& e : G[x]) {
            y = e.first; w = e.second;
            if (d[y] > d[x] + w) {
                d[y] = d[x] + w;
                Q.push({d[y], y});
            }
        }
    }
}

void Read() {
    fin >> N >> M >> K;
    G = vector<vector<PII>>(N + 1);
    C = VI(K); D = VVI(K + 1);
    dp = VVI(1 << K, VI(K, INF));
    for (int i = 0; i < K; i++)
        fin >> C[i];
    for (int i = 0, x, y, w; i < M; i++) {
        fin >> x >> y >> w;
        G[x].push_back({y, w});
        G[y].push_back({x, w});
    }
}