Cod sursa(job #969134)

Utilizator andrettiAndretti Naiden andretti Data 3 iulie 2013 16:21:00
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.66 kb
#include<stdio.h>
#include<vector>
#define pb push_back
#define mp make_pair
#define maxn 2005
#define maxk 20
#define maskl 1<<16
#define inf 999999999
using namespace std;

int n,m,nrc,dmin=inf,maskf,nh;
int c[maxk],d[maxn],x[maxn],poz[maxn];
int a[maxn][maxn];
int sol[maxk][maskl];
vector < pair<int,int> > l[maxn];

void cit()
{
    int i;
    int a,b,cost;

    scanf("%d%d%d",&n,&m,&nrc);
    for(i=1;i<=nrc;i++) scanf("%d",&c[i]);
    for(i=1;i<=m;i++)
    {
        scanf("%d%d%d",&a,&b,&cost);
        l[a].pb(mp(b,cost));
        l[b].pb(mp(a,cost));
    }
    maskf=(1<<nrc)-1;
}

void swap(int i,int j)
{
    int aux;
    aux=x[i];
    x[i]=x[j];
    x[j]=aux;
    poz[x[i]]=i;
    poz[x[j]]=j;
}

void heap_up(int k)
{
    if(k<=1) return;
    int i=k/2;
    if(d[x[i]]>d[x[k]])
    {
        swap(i,k);
        heap_up(i);
    }
}

void heap_dw(int k)
{
    int i=2*k;
    if(i<=nh)
    {
        if(i+1<=nh && d[x[i+1]]<d[x[i]]) i++;
        if(d[x[k]]>d[x[i]])
        {
            swap(i,k);
            heap_dw(i);
        }
    }
}

int extract()
{
    swap(1,nh);
    nh--;
    poz[x[nh+1]]=0;
    return x[nh+1];
}

void dijkstra(int nod)
{
    int i,k;
    for(i=1;i<=n;i++) { d[i]=inf; x[i]=i; poz[i]=i;}
    d[nod]=0;
    swap(1,nod);
    nh=n;

    while(nh>0)
    {
        k=extract();
        heap_dw(1);

        for(unsigned int i=0;i<l[k].size();i++)
         if( poz[l[k][i].first] && d[k]+l[k][i].second<d[l[k][i].first])
         {
             d[l[k][i].first]=d[k]+l[k][i].second;
             heap_up(poz[l[k][i].first]);
         }
    }
}

void drum()
{
    int i,j;

    dijkstra(1); for(i=1;i<=n;i++) a[1][i]=d[i];
    for(i=1;i<=nrc;i++)
    {
        dijkstra(c[i]);
        for(j=1;j<=n;j++) a[c[i]][j]=d[j];
    }

    for(i=1;i<=nrc;i++)
     sol[i][1<<(i-1)]=a[1][c[i]];
}

void det_min(int k,int mask)
{
    int i;
    int aux=inf;
    int nmask;
    if(sol[k][mask]) return;

    for(i=1;(mask>>(i-1))!=0;i++)
    if( ((mask>>(i-1))&1)==1 && i!=k)
    {
        nmask=(mask^(1<<(k-1)));
        if(sol[i][nmask]==0) det_min(i,nmask);
        aux=min(aux,sol[i][nmask]+a[c[i]][c[k]]);
    }
    sol[k][mask]=aux;
}

void solve()
{
    int i;
    int solf=inf;

    for(i=1;i<=nrc;i++)
    {
        det_min(i,maskf);
        solf=min(solf,sol[i][maskf]+a[c[i]][n]);
    }
    printf("%d",solf);
}
int main()
{
    freopen("ubuntzei.in","r",stdin);
    freopen("ubuntzei.out","w",stdout);

    cit();
    drum();
    if(nrc>0) solve();
    else printf("%d",a[1][n]);

    fclose(stdin);
    fclose(stdout);
    return 0;
}