Cod sursa(job #2850933)

Utilizator CaptnBananaPetcu Tudor CaptnBanana Data 17 februarie 2022 20:03:32
Problema Ubuntzei Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.68 kb
#include <bits/stdc++.h>

using namespace std;

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

const int K = 17, N = 2001, C = (1 << 16), INF32 = 0x3f3f3f3f;
int n, m, k, x, y, w, pr[K], dist[K][N], ans, dp[C][K]; // dp[i][j] = costul minim pt. a ajunge la starea i, stiind ca ultimul prieten vizitat este j
struct muchie{
    int y, w;
    bool operator < (muchie muc) const{
        return make_pair(w, y) < make_pair(muc.w, muc.y);
    }

    muchie(int spre, int cost){
        y = spre;
        w = cost;
    }
};
vector<muchie> c[N];
bool vis[N];

void djikstra(int start, int ind){
    set<muchie> s;
    for(int i = 1; i <= n; i++){
        dist[ind][i] = INF32;
        vis[i] = 0;
    }

    dist[ind][start] = 0;
    s.insert({start, 0});
    for(int i = 0; i < n; i++){
        int v = s.begin()->y; // pt. ca begin() returneaza pointer la priumul element
        s.erase(s.begin());
        vis[v] = 1;
        for(auto e: c[v]){
            if(!vis[e.y] && dist[ind][e.y] > dist[ind][v] + e.w){
                s.erase({e.y, dist[ind][e.y]});
                dist[ind][e.y] = dist[ind][v] + e.w;
                s.insert({e.y, dist[ind][e.y]});
            }
        }
    }
}

int main(){
    f >> n >> m >> k;
    for(int i = 1; i <= k; i++)
        f >> pr[i];

    for(int i = 0; i < m; i++){
        f >> x >> y >> w;
        muchie MX(y, w), MY(x, w);
        c[x].push_back(MX);
        c[y].push_back(MY);
    }

    f.close();
    for(int i = 1; i < (1 << (k + 1)); i++){
        for(int j = 0; j <= k + 1; j++)
            dp[i][j] = INF32;
    }

    // 0 - Cluj ; k + 1 - Vama Veche
    djikstra(1, 0); // calculare dist de la Cluj la restul prietenilor
    pr[k + 1] = n;
    for(int i = 1; i <= n; i++)
        dist[k + 1][i] = INF32;

    dist[k + 1][n] = 0;
    for(int i = 1; i <= k; i++){ // dist. de la fiecare prieten la toate celelalte localitati
        djikstra(pr[i], i);
        dp[(1 << (i - 1))][i] = dist[0][pr[i]]; // punem valoarea distantei de la Cluj la prieteni starii in care este vizitat doar prietenul respectiv
    }

    dp[1 << k][k + 1] = dist[0][n]; // pt. caz special in care k = 0
    for(int i = 1; i < (1 << (k + 1)); i++){
        for(int j = 1; j <= k; j++){
            if((1 << (j - 1)) & i){ // am fost deja pe la prietenul j
                for(int l = 1; l <= k + 1; l++){
                    if(((1 << (l - 1)) & i) == 0) // nu am fost inca pe la prietenul l
                        dp[i | (1 << (l - 1))][l] = min(dp[i | (1 << (l - 1))][l], dp[i][j] + dist[j][pr[l]]);
                }
            }
        }
    }

    g << dp[(1 << (k + 1)) - 1][k + 1];
    g.close();
}