Cod sursa(job #115469)

Utilizator pauldbPaul-Dan Baltescu pauldb Data 16 decembrie 2007 12:48:01
Problema Gather Scor 100
Compilator cpp Status done
Runda preONI 2008, Runda 2, Clasele 11-12 Marime 3.31 kb
#include <stdio.h>
#include <vector>

using namespace std;

#define us unsigned int
#define maxn 760
#define maxx 32768
#define maxk 16
#define pb push_back
#define inf 4294967295LL
#define min(a,b) (a < b ? a : b)

int n,m,K,l;
vector <int> a[maxn];
vector <us> b[maxn],cap[maxn];
int p[maxn],h[maxn],g[maxn];
us cost[maxn];
int unde[maxk];
us A[maxk][maxk][maxk];
us c[maxk][maxx];
us sol;

inline us solve(int nod,int x,int nr)
{
    if (c[nod][x]==inf)
    {
        int i;
        us aux;
        
/*        for (i=0;i<K;i++)
        {
            aux=solve(i,x,nr);
            if (0LL + aux +A[i][nod][nr]<c[nod][x]) c[nod][x]=aux + A[i][nod][nr];
        }*/
          
//        if (x&(1<<nod))

          nr--;
          for (i=0;i<K;i++)
            if (x&(1<<i) && i!=nod)
            {
                aux=solve(i,x-(1<<nod),nr);
                if (aux + 1LL * (nr+1) * A[i][nod][nr] < c[nod][x]) c[nod][x]=aux + (nr+1) * A[i][nod][nr];
            }
    }
    
    return c[nod][x];
}

inline void pop(int x)
{
    int aux;
    
    while (x/2>1 && cost[h[x]]<cost[h[x/2]])
    {
        aux=h[x];
        h[x]=h[x/2];
        h[x/2]=aux;
        
        p[h[x]]=x;
        p[h[x/2]]=x/2;
        
        x/=2;
    }
}

inline void push(int x)
{
    int aux,y=0;
    
    while (x!=y)
    {
        y=x;
        
        if (y*2<=l && cost[h[x]]>cost[h[y*2]]) x=y*2;
        if (y*2+1<=l && cost[h[x]]>cost[h[y*2+1]]) x=y*2+1;
        
        aux=h[x];
        h[x]=h[y];
        h[y]=aux;
        
        p[h[x]]=x;
        p[h[y]]=y;
    }
}

void Dijkstra(int nod,int capinf)
{
    int i;
    
    for (i=1;i<=n;i++)
    {
        cost[i]=inf;
        h[i]=i;
        p[i]=i;
    }
    
    l=n;
    cost[unde[nod]]=0;
    h[1]=unde[nod];
    h[unde[nod]]=1;
    p[1]=unde[nod];
    p[unde[nod]]=1;
    
    while (l>0)
    {
        for (i=0;i<g[h[1]];i++)
          if (cap[h[1]][i]>=capinf && 0LL+cost[h[1]] + b[h[1]][i]<cost[a[h[1]][i]])
          {
                cost[a[h[1]][i]] = cost[h[1]] + b[h[1]][i];
                pop(p[a[h[1]][i]]);
          }
          
        p[h[1]]=0;
        h[1]=h[l];
        p[h[1]]=1;
        h[l]=0;
        l--;
        
        if (l>1) push(1);
    }
    
    for (i=0;i<K;i++) A[nod][i][capinf]=cost[unde[i]];
}

int main()
{
    freopen("gather.in","r",stdin);
    freopen("gather.out","w",stdout);
    
    int x,y,i,j;
    us z,t;
    
    scanf("%d %d %d ",&K,&n,&m);
    
    for (i=0;i<K;i++) scanf("%d ",&unde[i]);
    unde[K]=1;
    
    for (i=1;i<=m;i++)
    {
        scanf("%d %d %u %u ",&x,&y,&z,&t);
        a[x].pb(y), b[x].pb(z), cap[x].pb(t);
        a[y].pb(x), b[y].pb(z), cap[y].pb(t);
    }
    
    for (i=1;i<=n;i++) g[i]=a[i].size();

    for (i=0;i<=K;i++)
        for (j=0;j<=K;j++) Dijkstra(j,i);
                
    for (i=0;i<K;i++)
      for (j=0;j<1<<K;j++) c[i][j]=inf;
      
    for (i=0;i<K;i++) c[i][1<<i]=A[K][i][0];
    
    sol=inf;
    
    for (i=0;i<K;i++) 
    {
        us aux=solve(i,(1<<K)-1,K);
        if (aux<sol) sol=aux;
    }
    
/*    for (i=0;i<K;i++)
    {
        for (j=0;j<1<<K;j++) printf("%u ",c[i][j]);
        printf("\n");
    }*/
    
    printf("%u\n",sol);
    
    return 0;
}