Cod sursa(job #1596071)

Utilizator Master011Dragos Martac Master011 Data 10 februarie 2016 19:25:09
Problema Gather Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.31 kb
#include<cstdio>
using namespace std;

const int nMax = 755, mMax = 1260, kMax = 16;
const int INF = 1999999999;
int h[nMax], posH[nMax];
long long d[nMax];
int nod[mMax * 2], lung[mMax * 2], urm[mMax * 2], lst[nMax];
long long dist[kMax][kMax][kMax];
int det[kMax], nrDet[mMax * 2];
long long C[1 << kMax][kMax];
int nrBit[1 << kMax];
int nre, n, m ,k, nrm;

void change(int p1, int p2){
    int aux = h[p1];
    h[p1] = h[p2];
    h[p2] = aux;

    posH[h[p1]] = p1;
    posH[h[p2]] = p2;
}

void up(int nodP){
    int tata = nodP >> 1;
    if(tata > 0 && d[h[tata]] > d[h[nodP]]){
        change(nodP, tata);
        up(tata);
    }
}

void down(int nodP){
    int fiu = nodP << 1;
    if(fiu <= nre){
        if(fiu + 1 <= nre && d[h[fiu + 1]] < d[h[fiu]])
            fiu++;
        if(d[h[fiu]] < d[h[nodP]]){
            change(nodP, fiu);
            down(fiu);
        }
    }
}

void push(int x){
    h[++nre] = x;
    posH[x] = nre;
    up(nre);
}

void pop(){
    change(1, nre);
    nre--;
    down(1);
}

void dijkstra(int nrM, int x){
    nre = 0;
    int nodS = det[x];
    for(int i = 1 ; i <= n ; ++i){
        d[i] = INF;
        posH[i] = 0;
    }
    d[nodS] = 0;
    push(nodS);

    int nodC, pos, vec;
    while(nre){
        nodC = h[1];
        pop();

        pos = lst[nodC]; vec = nod[pos];
        while(pos){
            if(nrDet[pos] >= nrM && d[vec] > d[nodC] + lung[pos]){
                d[vec] = d[nodC] + lung[pos];
                if(posH[vec]){
                    up(posH[vec]);
                }else{
                    push(vec);
                }
            }

            pos = urm[pos]; vec = nod[pos];
        }

    }

    for(int i = 0 ; i < k ; ++i){
        dist[nrM][x][i] = d[det[i]];
    }
}

inline void adauga(int x, int y, int val, int detM){
    nod[++nrm] = y;
    urm[nrm] = lst[x];
    lst[x] = nrm;
    lung[nrm] = val;
    nrDet[nrm] = detM;
}

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

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


    fscanf(in,"%d%d%d", &k, &n ,&m);
    det[0] = 1;
    for(int i = 1 ; i <= k ; ++i){
        fscanf(in,"%d", det + i);
    }
    ++k;
    int x, y, val, detM;
    for(int i = 0; i < m ; ++i){
        fscanf(in,"%d%d%d%d", &x, &y, &val, &detM);
        adauga(x, y, val, detM);
        adauga(y, x, val, detM);
    }
    for(int i = 0 ; i < k; ++i)
        for(int j = 0 ; j < k ; ++j)
            dijkstra(i, j);

    for(int i = 0 ; i < (1 << k) ; ++i)
        for(int j = 0 ; j < k ; ++j){
            C[i][j] = INF;
        }

    C[1][0] = 0;

    for(int i = 1; i < (1 << k) ; ++i)
        nrBit[i] = nrBit[i / 2] + (i % 2);

    for(int i = 1 ; i < (1 << k) ; ++i){
        for(int j = 0 ; j < k ; ++j){
            if(i & (1 << j)){
                for(int g = 0 ; g < k ; ++g){
                    if(j != g && i & (1 << g))
                        C[i][j] = minim(C[i][j], C[i ^ (1 << j)][g] + (nrBit[i] - 1) * dist[nrBit[i] - 2][g][j]);
                }
            }
        }
    }

    long long bst = INF;
    for(int i = 1 ; i < k ; ++i){
        bst = minim(bst, C[(1 << k) - 1][i]);
    }
    fprintf(out,"%lld\n", bst);
    return 0;
}