Cod sursa(job #2060092)

Utilizator PondorastiAlex Turcanu Pondorasti Data 7 noiembrie 2017 20:47:15
Problema Ubuntzei Scor 20
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.78 kb
#include <fstream>
#include <queue>
#include <vector>

using namespace std;

struct Alex {
    bool operator () (const pair<int, int> a, const pair<int, int> b) {
        return a.second > b.second;
    }
};

const int NMAX = 2000, KMAX = 15, INF = 2 * 1e8;
int n, m, k, x, y, z;
int preteni[KMAX + 5], dist[NMAX + 5][NMAX + 5];
int viz[NMAX + 5], dp[5 + KMAX][5 + (1 << KMAX)];

vector<pair<int, int> > g[NMAX + 2];
vector<int> cities;
priority_queue<pair<int, int>, vector<pair<int, int> >, Alex > q;

void read() {
    ifstream cin("ubuntzei.in");

    cin >> n >> m >> k;
    cities.push_back(1);
    for(int i = 1; i <= k; ++i) {
        cin >> preteni[i];
        cities.push_back(preteni[i]);
    }
    cities.push_back(n);
    for(int i = 1; i <= m; ++i) {
        cin >> x >> y >> z;
        g[x].push_back({y, z});
        g[y].push_back({x, z});
    }
}

inline int min(int a, int b) {
    return a < b ? a : b;
}

void dijkstra(int start) {
    for(int i = 1; i <= n; ++i)
        viz[i] = 0, dist[start][i] = INF;

    q.push({start, 0});
    dist[start][start] = 0;

    while(!q.empty()) {
        int node = q.top().first;
        q.pop();
        vector<pair<int, int> >::iterator vecini;
        if(!viz[node]) {
            for(vecini = g[node].begin(); vecini != g[node].end(); ++vecini) {
                if(dist[start][vecini -> first] > dist[start][node] + vecini -> second) {
                    dist[start][vecini -> first] = dist[start][node] + vecini -> second;
                    q.push({vecini -> first, dist[start][vecini -> first]});
                }
            }
        }
        viz[node] = 1;
    }
}

void findDist() {
    vector<int>::iterator oras;
    for(oras = cities.begin(); oras != cities.end(); ++oras) {
        dijkstra(*oras);
    }
}

void solve() {
    ofstream cout("ubuntzei.out");

    if(k == 0) {
        cout << dist[1][n] << "\n";
        return;
    }

    int limita = 1 << k;

    for(int stare = 1; stare < limita; ++stare) {
        for(int i = 1; i <= n; ++i)
            dp[i][stare] = INF;
    }

    for(int i = 1; i <= n; ++i) {
        dp[i][1 << (i - 1)] = dist[1][preteni[i]];
    }

    for(int stare = 1; stare < limita; ++stare) {
        for(int i = 1; i <= k; ++i) {
            if(stare & (1 << (i - 1)))
                for(int j = 1; j <= k; ++j)
                    if(i != j && stare & (1 << (j - 1)))
                    dp[i][stare] = min(dp[i][stare], dp[j][stare ^ (1 << (i - 1))] + dist[preteni[i]][preteni[j]]);
        }
    }
    int ans = INF;
    for(int i = 1; i <= k; ++i)
        ans = min(ans, dp[i][limita - 1] + dist[preteni[i]][n]);
    cout << ans << "\n";
}

int main() {

    read();
    findDist();
    solve();

    return 0;
}