Cod sursa(job #1596322)

Utilizator ZenusTudor Costin Razvan Zenus Data 10 februarie 2016 21:54:13
Problema Ubuntzei Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.34 kb
#include <bits/stdc++.h>

using namespace std;

const int INF = 1000000000;

int a[19] , d[19][19] , len[2009] , mark[2009] , p[19] , dp[19][1 << 17];
vector < pair < int , int > > g[2009];
int n , m , k;
priority_queue < pair < int , int > , vector < pair < int , int > > , greater < pair < int , int > > > ip;

void read()
{
    int i , x , y , z;

    scanf("%d" , &n);
    scanf("%d" , &m);

    scanf("%d" , &k);

    a[0] = 1 , a[k + 1] = n;
    for (i = 1 ; i <= k ; ++i)
    scanf("%d" , &a[i]);

    for (i = 1 ; i <= m ; ++i)
    {
        scanf("%d" , &x);
        scanf("%d" , &y);
        scanf("%d" , &z);
        g[x].push_back(make_pair(y , z));
        g[y].push_back(make_pair(x , z));
    }
}

void runDijkstra(int S)
{
    int i , j , x , z;

    for (i = 1 ; i <= n ; ++i)
    {
        len[i] = INF;
        mark[i] = 0;
    }

    ip.push(make_pair(0 , S));
    len[S] = 0;

    while (ip.size())
    {
        i = ip.top().second;
        ip.pop();

        if (mark[i]) continue;
        mark[i] = true;

        for (j = 0 ; j < g[i].size() ; ++j)
        {
            x = g[i][j].first;
            z = g[i][j].second;

            if (len[x] <= len[i] + z) continue;
            len[x] = len[i] + z;
            ip.push(make_pair(len[x] , x));
        }
    }
}

void runD()
{
    int i , j , ai , aj;

    for (i = 0 ; i <= k + 1 ; ++i)
    {
        ai = a[i];
        runDijkstra(ai);

        for (j = 0 ; j <= k + 1 ; ++j)
        {
            aj = a[j];
            d[i][j] = len[aj];
        }
    }
}

void solve()
{
    int result , mask , i , j , lmask;
    result = INF;

    for (mask = 0 ; mask < (1 << k) ; ++mask)
    {
        for (i = 1 ; i <= k ; ++i)
        dp[i][mask] = INF;

        for (i = 0 ; i < k ; ++i)
        if (mask & (1 << i))
        {
            lmask = mask - (1 << i);
            if (lmask == 0) dp[i + 1][mask] = d[i + 1][0];

            for (j = 0 ; j < k ; ++j)
            if (mask & (1 << j))
            {
                if (i == j) continue;
                dp[j + 1][mask] = min(dp[j + 1][mask] , dp[i + 1][lmask] + d[i + 1][j + 1]);
            }
        }
    }

    for (i = 1 ; i <= k ; ++i)
    result = min(result , dp[i][(1 << k) - 1] + d[i][k + 1]);

    printf("%d\n" , result);
}

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

read();
runD();
solve();

return 0;
}