Cod sursa(job #1610541)

Utilizator zertixMaradin Octavian zertix Data 23 februarie 2016 17:10:50
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.16 kb
#include <iostream>
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#define inf 0x3f3f3f3f
using namespace std;

int n,m,k,oras[20],dist[2005][2005],dp[66000][20],distx[2005];
vector <pair < int ,int > > g[2005];
priority_queue< pair < int ,int > > q;
void citire()
{
    scanf("%d%d",&n,&m);
    scanf("%d",&k);
    for (int i=0; i<k; ++i)
        scanf("%d",&oras[i]);
    for (int i=1; i<=m; ++i)
    {
        int nod1,nod2,c;
        scanf("%d%d%d",&nod1,&nod2,&c);
        g[nod1].push_back(make_pair(nod2,c));
        g[nod2].push_back(make_pair(nod1,c));
    }
    memset(dist,inf,sizeof(dist));
    memset(distx,inf,sizeof(distx));
}
void dijkstra(int s,int *d)
{
    q.push(make_pair(0,s));
    d[s]=0;
    while (!q.empty())
    {
        int nod=q.top().second;
        int c=-q.top().first;
        q.pop();

        for (vector <pair < int ,int > > :: iterator it=g[nod].begin(); it!=g[nod].end(); ++it)
            if (d[it->first]> c+it->second)
            {
                d[it->first]=c+it->second;
                q.push(make_pair(-d[it->first],it->first));
            }
    }

}
int ispow(int k)
{
    return (!(k & (k-1)));
}
int log (int k)
{
    int sum=0;
    while (k>1)
    {
        k/=2;
        sum++;
    }
    return sum;
}
int solve()
{
    dijkstra(1,distx);
    for (int i=0; i<k; ++i)
        dijkstra(oras[i],dist[i]);
    if (k==0)
        return distx[n];
    memset(dp,inf,sizeof(dp));
    for (int t=1; t<(1<<k); ++t)
    {
        if (ispow(t))
        {
            int logx=log(t);
            dp[t][logx]=distx[oras[logx]];
            continue;
        }
        for (int p=0; p<k; ++p)
            if (t & (1<<p))
                for (int l=0; l<k; ++l)
                    if (((1<<l) & t) && l!=p)
                        dp[t][p]=min(dp[t][p],dp[t-(1<<p)][l]+dist[l][oras[p]]);
    }
    int dis=inf;
    for (int i=0;i<k;++i)
        dis=min(dis,dp[(1<<k)-1][i]+dist[i][n]);
    return dis;
}
int main()
{
    freopen("ubuntzei.in","r",stdin);
    freopen("ubuntzei.out","w",stdout);
    citire();
    printf("%d",solve());
    return 0;
}