Cod sursa(job #2175898)

Utilizator savigunFeleaga Dragos-George savigun Data 16 martie 2018 19:50:10
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.82 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
using namespace std;

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

struct Edge { int y, dist; };
struct Node { int x, dist, viz; };

const int INF = 2e9 + 1;
const int MAXN = 2005;
int n, m, k, dist[MAXN];
int bit[MAXN]; // 0 daca nu sunt prieteni acolo sau indexul bitului corespunzator nodului, daca sunt prieteni
int viz[MAXN];
vector<Edge> g[MAXN];

class Cmp {
public:
    bool operator()(Node a, Node b) {
        return a.dist > b.dist;
    }
};

bool other_friends(int a, int b) {
    while (a) {
        if ((a & 1 == 1) && (b & 1 == 0)) return true;
        a >>= 1;
        b >>= 1;
    }
    return false;
}

void Dijkstra() {
    priority_queue<Node, vector<Node>, Cmp> q;
    for (int i = 1; i <= n; ++i) dist[i] = INF;
    dist[1] = 0;
    q.push({1, 0, 0});

    int k_mask = (1 << k) - 1;

    while (!q.empty()) {
        Node now = q.top(); q.pop();
        int x = now.x;
        dist[x] = now.dist;
        viz[x] = now.viz;

        if (x == n && viz[x] == k_mask) {
            out << dist[x];
            return;
        }

        if (bit[x] != -1) {
            viz[x] |= (1 << bit[x]);
        }

        for (Edge &e : g[x]) {
            int y = e.y;
            if (dist[x] + e.dist < dist[y] || other_friends(viz[x], viz[y])) {
                q.push({y, dist[x] + e.dist, viz[x]});
            }
        }
    }
}

int main()
{

    in >> n >> m >> k;
    for (int i = 1; i <= n; ++i) bit[i] = -1;
    for (int i = 0, x; i < k; ++i) {
        in >> x;
        bit[x] = i;
    }

    for (int i = 1, x, y, d; i <= m; ++i) {
        in >> x >> y >> d;
        g[x].push_back({y, d});
        g[y].push_back({x, d});
    }

    Dijkstra();

    return 0;
}