Cod sursa(job #1610425)

Utilizator Master011Dragos Martac Master011 Data 23 februarie 2016 15:28:03
Problema Ubuntzei Scor 75
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.09 kb
#include<cstdio>
#include<cstring>
using namespace std;

const int nMax = 2010, mMax = 10010, kMax = 18, cMax = 65540, INF =  0x3f3f3f3f;
int lst[nMax], urm[mMax * 2], val[mMax * 2], cost[mMax * 2];
int heap[nMax], poz[nMax], dist[kMax][nMax], din[cMax][kMax], v[kMax];
int n, m, k, nrc, vf;

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

void adauga(int x, int y, int c){
    val[++nrc] = y;
    urm[nrc] = lst[x];
    cost[nrc] = c;
    lst[x] = nrc;
}

void change(int i, int j){
        int aux;

        poz[heap[i]] = j;
        poz[heap[j]] = i;
        aux = heap[i];
        heap[i] = heap[j];
        heap[j] = aux;
}

void up(int p, int ind){
    while(dist[ind][heap[p]] < dist[ind][heap[p/2]] && p >= 1){
        change(p, p / 2);

        p /= 2;
    }
}

void down(int p, int ind){
    int f;
     while(p <= vf){
        f = p << 1;
        if(f > vf) return;
        if(f + 1 < vf && dist[ind][heap[f]] > dist[ind][heap[f+1]]){
            f++;
        }
        if(dist[ind][heap[p]] > dist[ind][heap[f]]){
            change(p, f);
            p = f;
        }else return;
    }
}

void dijktrsa(int ind, int nodS){
    for(int i = 1 ; i <= n ; ++i) dist[ind][i] = INF, poz[i] = -1;

    dist[ind][nodS] = 0;
    heap[vf++] = nodS;
    poz[nodS] = 0;

    int nodC, vec, u, co;
    while(vf){
        nodC = heap[0];
        change(0, vf - 1);
        --vf;
        down(0, ind);

        u = lst[nodC], vec = val[u], co = cost[u];
        while(u){
            if(dist[ind][vec] > dist[ind][nodC] + co){
                dist[ind][vec] = dist[ind][nodC] + co;

                if(poz[vec] == -1){
                    heap[vf] = vec;
                    poz[vec] = vf;
                    vf++;
                }

                up(poz[vec], ind);
            }

            u = urm[u]; vec = val[u], co = cost[u];
        }
    }
}

int main(){
    FILE *in = fopen("ubuntzei.in","r");
    FILE *out = fopen("ubuntzei.out","w");

    fscanf(in,"%d%d%d", &n, &m, &k);
    for(int i = 1 ; i <= k ; ++i) fscanf(in,"%d", v + i);

    for(int i = 1 , x, y, c; i <= m ; ++i){
        fscanf(in,"%d%d%d", &x, &y, &c);
        adauga(x,y,c);
        adauga(y,x,c);
    }
    v[0] = 1;
    for(int i = 0 ; i <= k ; ++i){
        vf = 0;
        dijktrsa(i, v[i]);
    }

    int lim = 1 << (k + 1);

    for(int i = 1 ; i < lim ; ++i)
        for(int j = 0; j <= k ; ++j)
            din[i][j] = INF;

    din[1][0] = 0;
    for(int i = 1 ; i < lim ; ++i){
        for(int j = 0 ; j <= k ; ++j){
            //if(i != 1 || j != 0) din[i][j] = INF;
            if(i & (1 << j)){
                for(int ki = 0 ; ki <= k ; ++ki){
                    if((i & (1 << ki)) && ki != j){
                        din[i][j] = minim(din[i][j], din[i ^ (1 << j)][ki] + dist[ki][v[j]]);
                    }
                }
            }
        }
    }

    int sol = INF;
    for(int i = 0 ; i <= k ; ++i){
        sol = minim(sol, din[lim - 1][i] + dist[i][n]);
    }

    fprintf(out,"%d\n", sol);
    return 0;
}