Cod sursa(job #115807)

Utilizator sealTudose Vlad seal Data 16 decembrie 2007 23:07:58
Problema Gather Scor 30
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.56 kb
#include<stdio.h>
#define Nm 751
#define Km 16
#define Inf ((1ll<<32)*Nm)
#define min(a,b) ((a)<(b)?(a):(b))
int G[Nm][Nm],C[Nm][Nm],K[Nm][Nm],D[Nm],H[Nm],P[Nm],N[Km],h,n,k;
long long Dm[Km][Km][Km],M[Km][1<<Km-1],Dist[Nm],ans;

void read()
{
    int i,m,a,b,c,d;

    freopen("gather.in","r",stdin);
    scanf("%d%d%d",&k,&n,&m);
    for(i=0;i<k;++i)
        scanf("%d",N+i);
    N[k]=1;
    while(m--)
    {
        scanf("%d%d%d%d",&a,&b,&c,&d);
        G[a][D[a]]=b;
        C[a][D[a]]=c;
        K[a][D[a]++]=d;
        G[b][D[b]]=a;
        C[b][D[b]]=c;
        K[b][D[b]++]=d;
    }
}

void sink(int x)
{
    int v=H[x],son=x<<1;

    while(son<=h)
    {
        if(son<h && Dist[H[son|1]]<Dist[H[son]])
            son|=1;
        if(Dist[v]<=Dist[H[son]])
            break;
        H[x]=H[son]; P[H[x]]=x;
        x=son; son<<=1;
    }
    H[x]=v; P[v]=x;
}

void lift(int x)
{
    int v=H[x];

    while(x>1 && Dist[v]<Dist[H[x>>1]])
    {
        H[x]=H[x>>1];
        P[H[x]]=x;
        x>>=1;
    }
    H[x]=v; P[v]=x;
}

void Dijkstra(int s, int d)
{
    int x,y,c,i;

    Dist[N[s]]=0; H[h=1]=N[s]; P[N[s]]=1;
    for(i=1;i<=n;++i)
        if(i!=N[s])
        {
            Dist[i]=Inf;
            H[++h]=i; P[i]=h;
        }

    while(h)
    {
        x=H[1];
        H[1]=H[h--];
        sink(1);

        for(i=0;i<D[x];++i)
        {
            if(d>K[x][i])
                continue;
            y=G[x][i]; c=C[x][i];
            if(Dist[x]+c<Dist[y])
            {
                Dist[y]=Dist[x]+c;
                lift(y);
            }
        }
    }

    for(i=0;i<k;++i)
        Dm[s][d][i]=Dist[N[i]];
}
    
void solve()
{
    int Bits[1<<Km-1],i,j,l;
    long long v;

    for(i=0;i<k;++i)
        for(j=1;j<k;++j)
            Dijkstra(i,j);
    Dijkstra(k,0);

    Bits[0]=0; Bits[1]=1;
    for(i=2;i<1<<k;++i)
        Bits[i]=Bits[i>>1]+(i&1);

    for(j=(1<<k)-2;j;--j)
        for(i=0;i<k;++i)
        {
            if(!(j&1<<i))
                continue;
            M[i][j]=Inf;
            for(l=0;l<k;++l)
            {
                if(j&1<<l)
                    continue;
                v=Dm[i][Bits[j]][l]*(Bits[j]+1)+M[l][j|1<<l];
                M[i][j]=min(M[i][j],v);
            }
        }

    ans=Inf;
    for(i=0;i<k;++i)
        ans=min(ans,Dm[k][0][i]+M[i][1<<i]);
}

void write()
{
    freopen("gather.out","w",stdout);
    printf("%lld\n",ans);
}

int main()
{
    read();
    solve();
    write();
    return 0;
}