Cod sursa(job #1547779)

Utilizator Burbon13Burbon13 Burbon13 Data 9 decembrie 2015 21:33:06
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.61 kb
#include <cstdio>
#include <queue>
#include <vector>
#include <queue>
#include <cstring>
#define f first
#define s second
using namespace std;

const int kmx = 16;
const int nmx = 2002;
const int inf = 0x3f3f3f3f;

int n,m,k,oras[kmx],dp[1<<kmx][kmx],dist[kmx][nmx],l[nmx]; /// dist[x][y] din orasul x pana in nodul y
vector <pair<int,int> > g[nmx];                            /// dp[x][y] costul format orasele lui x pana in orasul y
priority_queue <pair<int,int> > q;

void citire() {
    scanf("%d %d %d", &n, &m, &k);
    for(int i = 0; i < k; ++i)
        scanf("%d", &oras[i]);
    int nod1,nod2,cost;
    for(int i = 1; i <= m; ++i) {
        scanf("%d %d %d", &nod1, &nod2, &cost);
        g[nod1].push_back(make_pair(nod2,cost));
        g[nod2].push_back(make_pair(nod1,cost));
    }
}

void setare_matrice(){
    memset(l,inf,sizeof(l));
    memset(dist,inf,sizeof(dist));
}

void dijkstra(int nod, int *p) {
    p[nod] = 0;
    q.push(make_pair(0,nod));
    while(not q.empty()) {
        nod = q.top().s;
        q.pop();
        for(vector<pair<int,int> >::iterator it = g[nod].begin(); it != g[nod].end(); ++it)
            if(p[it->first] > p[nod] + it->second) {
                p[it->first] = p[nod] + it->second;
                q.push(make_pair(-p[it->first],it->first));
            }
    }
}

bool ispow2(int nr){
    return (not (nr & (nr - 1)));
}

int getpow2(int nr){
    int sum = 0;
    while(nr > 1){
        nr /= 2;
        ++ sum;
    }
    return sum;
}

void dinamica(){
    memset(dp,inf,sizeof(dp));
    int p2 = 0;
    for(int t = 1; t < (1 << k); ++t){
        if(ispow2(t)){
            int loc = getpow2(t);
            dp[t][loc] = l[oras[loc]];
            if(not p2)
                p2 = 1;
            else
                p2 *= 2;
            continue;
        }
        for(int p = 0; p < k; ++p) /// se termina in nodul p
            if((1 << p) & t)
                for(int j = 0; j < k; ++j) /// facem leg catena - j - p;
                    if(j != p && ((1 << j) & t))
                        dp[t][p] = min(dp[t][p],dp[t-(1 << p)][j] + dist[j][oras[p]]);
    }
    int total = inf;
    for(int i = 0; i < k;++i)
        total = min(total,dp[(1<<k)-1][i] + dist[i][n]);
    printf("%d\n", total);
}

int main() {
    freopen("ubuntzei.in", "r", stdin);
    freopen("ubuntzei.out", "w", stdout);
    citire();
    setare_matrice();
    dijkstra(1,l);
    if(k == 0){
        printf("%d\n", l[n]);
        return 0;
    }
    for(int i = 0; i < k; ++i)
        dijkstra(oras[i],dist[i]);
    dinamica();
    return 0;
}