Cod sursa(job #1803625)

Utilizator bogdan10bosBogdan Sitaru bogdan10bos Data 11 noiembrie 2016 17:12:43
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.82 kb
#include <bits/stdc++.h>

using namespace std;

#define FILE_IO

typedef pair<int, int> pii;
typedef pair<int, pii> p3i;

int N, M, K;
int B, b[25];
int need[25];
int p2[33005];
int d[25][2005];
int dp[33005][25];
vector <pii> edg[2005];
priority_queue < pii, vector<pii>, greater<pii> > hp;

void dijkstra(int id, int start)
{
    for(int i = 1; i <= N; i++)
        d[id][i] = 1 << 30;
    d[id][start] = 0;
    hp.push({0, start});
    while(!hp.empty())
    {
        int val = hp.top().first;
        int nod = hp.top().second;
        hp.pop();

        if( d[id][nod] < val ) continue;
        d[id][nod] = val;
        for(auto edge: edg[nod])
            if(d[id][edge.first] > val + edge.second)
            {
                d[id][edge.first] = val + edge.second;
                hp.push( {val + edge.second, edge.first} );
            }
    }
}

int gint()
{
    char ch = getchar();
    while(ch < '0' || '9' < ch)
        ch = getchar();

    int x = 0;
    while('0' <= ch && ch <= '9')
    {
        x = x * 10 + ch - '0';
        ch = getchar();
    }
    return x;
}

int main()
{
    #ifdef FILE_IO
    freopen("ubuntzei.in", "r", stdin);
    freopen("ubuntzei.out", "w", stdout);
    #endif

    N = gint();
    M = gint();
    K = gint();
    need[0] = 1;
    for(int i = 1; i <= K; i++)
        need[i] = gint();
    need[K + 1] = N;

    for(int i = 1; i <= M; i++)
    {
        int x, y, z;
        x = gint();
        y = gint();
        z = gint();
        edg[x].push_back({y, z});
        edg[y].push_back({x, z});
    }

    for(int i = 0; i <= K; i++)
        dijkstra(i, need[i]);

    for(int i = 2; i <= 1 << K; i++)
    {
        p2[i] = p2[i - 1];
        if( (2 << p2[i]) == i )
            p2[i]++;
    }

    for(int msk = 1; msk < 1 << K; msk++)
    {
        if( !(msk & (msk - 1)) )
        {
            dp[msk][ p2[msk] ] = d[0][ need[ p2[msk] + 1 ] ];
            continue;
        }

        int aux = msk;
        B = 0;
        while(aux)
        {
            int p = p2[aux];
            dp[msk][p] = 1 << 30;
            aux -= (1 << p);
            b[ ++B ] = p;
        }

        for(int ii = 1; ii <= B; ii++)
            for(int jj = ii + 1; jj <= B; jj++)
            {
                int i = b[ii];
                int j = b[jj];
                dp[msk][i] = min(dp[msk][i], dp[msk ^ (1 << i)][j] + d[j + 1][ need[i + 1] ]);
                dp[msk][j] = min(dp[msk][j], dp[msk ^ (1 << j)][i] + d[i + 1][ need[j + 1] ]);
            }
    }

    if(K == 0)
    {
        printf("%d\n", d[0][N]);
        return 0;
    }

    int ans = 1 << 30;
    int msk = (1 << K) - 1;
    for(int i = 0; i < K; i++)
        ans = min(ans, dp[msk][i] + d[i + 1][N]);
    printf("%d\n", ans);

    return 0;
}