Cod sursa(job #2184259)

Utilizator andreicoman299Coman Andrei andreicoman299 Data 23 martie 2018 21:25:39
Problema Gather Scor 90
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.54 kb
///I GIVE UP

#include <cstdio>
#define INF 1000000000000000000LL
#define MAXN 750
#define MAXM 1250
#define MAXK 15
int q, n, val[2*MAXM+1], cost[2*MAXM+1], cond[2*MAXM+1], next[2*MAXM+1], lista[MAXN+1], heap[MAXN+1], poz[MAXN+1], v[MAXN+1], gata[MAXN+1];
long long dp[1<<MAXK][MAXK], d[MAXK][MAXK][MAXK], sol[MAXN+1], dist[MAXN+1];
inline void adauga(int x, int y, int z, int t){
    q++;
    val[q]=y;
    cost[q]=z;
    cond[q]=t;
    next[q]=lista[x];
    lista[x]=q;
}
inline int tata(int p){
    return p/2;
}
inline int fiust(int p){
    return 2*p;
}
inline int fiudr(int p){
    return 2*p+1;
}
inline void schimb(int p, int q){
    int aux=heap[p];
    heap[p]=heap[q];
    heap[q]=aux;
    poz[heap[p]]=p;
    poz[heap[q]]=q;
}
inline void urcare(int p){
    while((p>1)&&(dist[heap[p]]<dist[heap[tata(p)]])){
        schimb(p, tata(p));
        p=tata(p);
    }
}
inline void coborare(int p){
    int q, f=1;
    while((f)&&(fiust(p)<=n)){
        q=fiust(p);
        if((fiudr(p)<=n)&&(dist[heap[fiudr(p)]]<dist[heap[q]])){
            q=fiudr(p);
        }
        if(dist[heap[q]]<dist[heap[p]]){
            schimb(p, q);
            p=q;
        }else{
            f=0;
        }
    }
}
inline void dijkstra(int s, int e){
    int i, t, x, p;
    for(i=1; i<=n; i++){
        dist[i]=INF;
        heap[i]=i;
        poz[i]=i;
        gata[i]=0;
        sol[i]=INF;
    }
    dist[s]=0;
    urcare(poz[s]);
    t=1;
    while(t>0){
        x=heap[1];
        gata[x]=1;
        sol[x]=dist[x];
        dist[x]=INF;
        t--;
        coborare(1);
        p=lista[x];
        while(p){
            if((gata[val[p]]==0)&&(cond[p]>=e)&&(dist[val[p]]>sol[x]+cost[p])){
                if(dist[val[p]]==INF){
                    t++;
                }
                dist[val[p]]=sol[x]+cost[p];
                urcare(poz[val[p]]);
            }
            p=next[p];
        }
    }
}
int main(){
    int k, m, i, j, p, s, x, y, z, t, maxt;
    long long ans;
    FILE *fin, *fout;
    fin=fopen("gather.in", "r");
    fout=fopen("gather.out", "w");
    fscanf(fin, "%d%d%d", &k, &n, &m);
    for(i=0; i<k; i++){
        fscanf(fin, "%d", &v[i]);
    }
    maxt=0;
    for(i=0; i<m; i++){
        fscanf(fin, "%d%d%d%d", &x, &y, &z, &t);
        adauga(x, y, z, t);
        adauga(y, x, z, t);
        if(t>maxt){
            maxt=t;
        }
    }
    for(i=0; i<k; i++){
        for(j=0; j<k; j++){
            dijkstra(v[i], j);
            for(p=0; p<k; p++){
                d[j][i][p]=sol[v[p]];
            }
        }
    }
    for(i=0; i<(1<<k); i++){
        for(j=0; j<k; j++){
            dp[i][j]=INF;
        }
    }
    dijkstra(1, 0);
    for(i=0; i<k; i++){
        dp[1<<i][i]=sol[v[i]];
    }
    for(i=0; i<(1<<k); i++){
        for(j=0; j<k; j++){
            if((i!=(1<<j))&&(i&(1<<j))){
                s=0;
                for(p=0; p<k; p++){
                    if(i&(1<<p)){
                        s++;
                    }
                }
                for(p=0; p<k; p++){
                    if((p!=j)&&(i&(1<<p))&&(d[s-1][p][j])&&(dp[i][j]>dp[i^(1<<j)][p]+s*d[s-1][p][j])){
                        dp[i][j]=dp[i^(1<<j)][p]+s*d[s-1][p][j];
                    }
                }
            }
        }
    }
    ans=dp[(1<<k)-1][0];
    for(i=1; i<k; i++){
        if(ans>dp[(1<<k)-1][i]){
            ans=dp[(1<<k)-1][i];
        }
    }
    fprintf(fout, "%lld\n", ans);
    fclose(fin);
    fclose(fout);
    return 0;
}