Cod sursa(job #115572)

Utilizator VmanDuta Vlad Vman Data 16 decembrie 2007 12:59:38
Problema Gather Scor 0
Compilator cpp Status done
Runda preONI 2008, Runda 2, Clasele 11-12 Marime 4.31 kb
using namespace std;
#include <stdio.h>
#include <vector>

#define Kmax 20
#define Nmax 800
#define Mmax 1300
#define infinit 2147000000
#define Pmax 32800

int K,N,M;
int det[Kmax];
int A[Mmax],B[Mmax],C[Mmax],D[Mmax];
int dist[Kmax][Kmax][Kmax];
int heap[Nmax],d[Nmax],ph[Nmax],nrh;
int a[Kmax][Pmax];
vector<int> g[Nmax];

void citire()
{
 int i;
 freopen("d:/programe/bc/bin/gather.in","r",stdin);
 scanf("%d %d %d",&K,&N,&M);
 for (i=1;i<=K;++i)
     scanf("%d",&det[i]);
 for (i=1;i<=M;++i)
     {
      scanf("%d %d %d %d",&A[i],&B[i],&C[i],&D[i]);
      g[A[i]].push_back(i);
      g[B[i]].push_back(i);
     }
 fclose(stdin);
}

int heap_out()
{
 int t,f1,f2,aux,v;
 v=heap[1];
 heap[1]=heap[nrh];
 ph[heap[1]]=1;
 --nrh;
 if (nrh<2) return v;
 t=1;
 while ((t<<1)<nrh)
       {
        f1=t<<1;
        if (f1<nrh)
           {
            f2=f1+1;
            if (d[heap[f1]]<d[heap[f2]])
               if (d[heap[f1]]<d[heap[t]])
                  {
                   aux=heap[f1];
                   heap[f1]=heap[t];
                   heap[t]=aux;
                   ph[heap[t]]=t;
                   ph[heap[f1]]=f1;
                   t=f1;
                  }
               else ;
             else if (d[heap[f2]]<d[heap[t]])
                  {
                   aux=heap[f2];
                   heap[f2]=heap[t];
                   heap[t]=aux;
                   ph[heap[t]]=t;
                   ph[heap[f2]]=f2;
                   t=f2;
                  }
           }
          else
           if (d[heap[f1]]<d[heap[t]])
              {
               aux=heap[f1];
               heap[f1]=heap[t];
               heap[t]=aux;
               ph[heap[t]]=t;
               ph[heap[f1]]=f1;
               t=f1;
              }
       }
 return v;
}

void heap_update(int nod)
{
 int t,f,aux;
 if (ph[nod]==0)
    {
     ++nrh;
     heap[ph[nod]=nrh]=nod;
     f=nrh;
     t=f>>1;
     while (t>0)
        if (d[heap[f]]<d[heap[t]])
            {
             aux=heap[f];
             heap[f]=heap[t];
             heap[t]=aux;
             ph[heap[f]]=f;
             ph[heap[t]]=t;
             f=t;
             t=f>>1;
            }
        else break;
    }
 else
     {
     f=ph[nod];
     t=f>>1;
     while (t>0)
        if (d[f]<d[t])
            {
             aux=heap[f];
             heap[f]=heap[t];
             heap[t]=aux;
             ph[heap[f]]=f;
             ph[heap[t]]=t;
             f=t;
             t=f>>1;
            }
        else break;
     }
}

void dijkstra(int s,int nrd)
{
 int i,nod;
 vector<int>::iterator it;
 //init
 memset(heap,0,sizeof(heap));
 memset(ph,0,sizeof(ph));
 nrh=0;
 for (i=1;i<=N;++i)
     d[i]=infinit;
 d[det[s]]=0;
 heap_update(det[s]);
 //dijkstra
 while (nrh>0)
       {
        nod=heap_out();
        for (it=g[nod].begin();it<g[nod].end();++it)
            if (D[*it]>=nrd)
               {
                if (C[ *it ] + d[nod] < d[ A[*it] ])
                   {
                    d[ A[*it] ] = C[ *it ] + d[nod];
                    heap_update( A[*it] );
                   }
               if (C[ *it ] + d[nod] < d[ B[*it] ])
                   {
                    d[ B[*it] ] = C[ *it ] + d[nod];
                    heap_update( B[*it] );
                   }
               }
       }
 for (i=1;i<=K;++i)
      dist[nrd][s][i]=d[det[i]];
}

void compute()
{
 int i,j;
 //gigel catre primu detinut
 det[0]=1;
 dijkstra(0,0);
 //drumuri intre detinuti
 for (i=1;i<=K;++i)
   for (j=1;j<=K;++j)
     dijkstra(i,j);
}

void dinamica()
{
 int i,j,k,p[Kmax],nrd;
 p[0]=1;
 for (i=1;i<=K;++i)
     p[i]=p[i-1]<<1;
 for (i=1;i<=K;++i)
    a[1][p[i-1]]=dist[0][0][i]+1;
 for (i=3;i<p[K];++i)
     {
      nrd=0;
      for (j=0;j<K;++j)
          if (i&p[j]) ++nrd;
      if (nrd==1) continue;
      for (j=0;j<K;++j)
          if (i&p[j])
             for (k=0;k<K;++k)
                 if ((k!=j)&&(i&p[k])&&((a[nrd][i]==0)||(a[nrd][i]>a[nrd-1][i-p[j]]+nrd*dist[nrd-1][k+1][j+1])))
                    a[nrd][i]=a[nrd-1][i-p[j]]+nrd*dist[nrd-1][k+1][j+1];
     }
 freopen("gather.out","w",stdout);
 printf("%d",a[K][p[K]-1]-1);
 fclose(stdout);
}

int main()
{
 citire();
 compute();
 dinamica();
 return 0;
}