Cod sursa(job #1500119)

Utilizator PopoviciRobertPopovici Robert PopoviciRobert Data 11 octombrie 2015 15:46:18
Problema Gather Scor 20
Compilator c Status done
Runda Arhiva de probleme Marime 4.1 kb
#include <stdio.h>
#include <stdlib.h>
#define MAXN 750   //celule
#define MAXK 15    //hoti
#define MAXM 1250  //muchii
#define INF 2000000000
int hot[MAXK],celula1[2*MAXM+1],ind1[MAXN+1],next1[2*MAXM+1],ldrum1[2*MAXM+1],capdrum1[2*MAXM+1],vfhot[MAXN+1],con=1;  //primul graf
int distanta[MAXK][MAXK][MAXK],H[MAXM+1],celulaH[MAXM],vfcelH[MAXN];  //calcul muchii pt. graful doi
int A[MAXK][1<<(MAXK)]; //dinamica
inline void add(int a,int b,int c,int d){
    celula1[con]=a;
    next1[con]=ind1[b];
    ind1[b]=con;
    ldrum1[con]=c;
    capdrum1[con]=d;
    con++;
}
inline void dijkstra(int nod,int cap,int n){
    int conH=1,nrnod=1,poz,i;
    poz=ind1[hot[nod]];
    vfcelH[hot[nod]]=1;
    while(poz){
        if(capdrum1[poz]>=cap){
            H[conH]=ldrum1[poz];
            celulaH[conH]=celula1[poz];
            urcare(conH);
            conH++;
        }
        poz=next1[poz];
    }
    while(nrnod<n&&conH>0){
        if(vfhot[celulaH[1]]>0)
            distanta[nod][vfhot[celulaH[1]]-1][cap]=H[1];
        if(celulaH[1]==1)
            distanta[nod][nod][cap]=H[1];
        vfcelH[celulaH[1]]=1;
        poz=ind1[celulaH[1]];
        while(poz){
            if(capdrum1[poz]>=cap&&vfcelH[celula1[poz]]==0){
                H[conH]=ldrum1[poz]+H[1];
                celulaH[conH]=celula1[poz];
                urcare(conH);
                conH++;
            }
            poz=next1[poz];
        }
        conH--;
        H[1]=H[conH];
        celulaH[1]=celulaH[conH];
        coborare(1,conH);
        nrnod++;
    }
    for(i=1;i<=n;i++)
        vfcelH[i]=0;
}
inline void swap(int x,int y,int *v){
    int aux=v[x];
    v[x]=v[y];
    v[y]=aux;
}
inline int t_nod(int nod){
    return nod/2;
}
inline int l_nod(int nod){
    return 2*nod;
}
inline int r_nod(int nod){
    return 2*nod+1;
}

inline void urcare(int nod){
    int flag=1;
    while(t_nod(nod)&&flag){
        flag=t_nod(nod);
        if(H[t_nod(nod)]>H[nod]){
            swap(nod,t_nod(nod),H);
            swap(nod,t_nod(nod),celulaH);
            nod=t_nod(nod);
        }
        if(flag!=nod)
            flag=0;
    }
}
inline void coborare(int nod,int n){
    int flag=1;
    while(l_nod(nod)<n&&flag){
        flag=nod;
        if(H[l_nod(nod)]<H[nod]&&(H[r_nod(nod)]>H[l_nod(nod)]||r_nod(nod)>=n)){
            swap(nod,l_nod(nod),H);
            swap(nod,l_nod(nod),celulaH);
            nod=l_nod(nod);
        }
        else
           if(r_nod(nod)<n&&H[r_nod(nod)]<H[nod]){
                swap(nod,r_nod(nod),H);
                swap(nod,r_nod(nod),celulaH);
                nod=r_nod(nod);
           }
        if(nod==flag)
             flag=0;
    }
}
int main(){
    FILE*fi,*fout;
    int i,j,n,m,k,a,b,c,d,x,nr,priz,min,z;
    fi=fopen("gather.in" ,"r");
    fout=fopen("gather.out" ,"w");
    fscanf(fi,"%d%d%d" ,&k,&n,&m);
    for(i=0;i<k;i++){
        fscanf(fi,"%d" ,&hot[i]);
        vfhot[hot[i]]=i+1;
    }
    for(i=0;i<m;i++){
        fscanf(fi,"%d%d%d%d" ,&a,&b,&c,&d);
        add(a,b,c,d);
        add(b,a,c,d);
    }
    for(i=0;i<k;i++)
        for(j=0;j<k;j++)
           for(z=0;z<k;z++)
               distanta[i][j][z]=INF;
    for(i=0;i<k;i++)
       for(j=0;j<k;j++)
            dijkstra(i,j,n);
    for(i=0;i<k;i++)
        for(j=0;j<(1<<k);j++)
           A[i][j]=INF;
    for(i=0;i<k;i++)
        A[i][(1<<i)]=distanta[i][i][0];
    for(j=0;j<(1<<k);j++)
       for(i=0;i<k;i++)
            if((j&(1<<i))>0&&(1<<i)!=j){
               nr=j;
               priz=0;
               while(nr){
                   priz+=(nr&1);
                   nr>>=1;
               }
               for(x=0;x<k;x++)
                   if(A[x][j^(1<<i)]<INF&&distanta[x][i][priz-1]<INF&&i!=x&&((j&(1<<x))>0)&&A[i][j]>A[x][j^(1<<i)]+priz*distanta[x][i][priz-1]){
                      A[i][j]=A[x][j^(1<<i)]+priz*distanta[x][i][priz-1];

            }
        }
    min=INF;
    for(i=0;i<k;i++)
        if(min>A[i][(1<<k)-1])
           min=A[i][(1<<k)-1];
    fprintf(fout,"%d" ,min);
    fclose(fi);
    fclose(fout);
    return 0;
}