Cod sursa(job #1392226)

Utilizator Al3ks1002Alex Cociorva Al3ks1002 Data 18 martie 2015 14:45:20
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.52 kb
// dp[i][j] = costul minim pentru a ajunge in j trecand cel putin o data prin orasele din multimea i
// dp[i][j] = dp[i-{j}][k]+Dist[j][k] , pentru orice j, k apartinand multimii i
// complexitate finala: O(K*M*log(N)+2^K*K^2)

#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>

#define PII pair<int,int>
#define pb push_back
#define mp make_pair

using namespace std;

const int KMAX = 15;
const int NMAX = 2005;
const int INF = 1 << 30;

int K, i, j, k, n, m, p, x, y, c, from, where, costwhere, aux, sol;
int P[KMAX], Dist[NMAX][NMAX], dp[1 << KMAX][KMAX];

vector<PII> V[NMAX];

struct cmp
{
    bool operator () (PII a, PII b)
    {
        return a.second > b.second;
    }
};
priority_queue<PII, vector<PII>, cmp> Q;

void Dijkstra(int x)
{
    int d[NMAX], i;

    for(i = 1; i <= n; i++)
        d[i] = INF;

    d[x] = 0;
    Q.push(mp(x, 0));

    while(!Q.empty())
    {
        from = Q.top().first;
        Q.pop();
        for(vector<PII>::iterator it = V[from].begin(); it != V[from].end(); it++)
        {
            where = it->first;
            costwhere = it->second;
            if(d[from] + costwhere < d[where])
            {
                d[where] = d[from] + costwhere;
                Q.push(mp(where, d[where]));
            }
        }
    }

    for(i = 1; i <= n; i++)
        Dist[x][i] = d[i];
}

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

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

    for(i = 0; i < p; i++)
        scanf("%d", &P[i]);

    for(; m; m--)
    {
        scanf("%d%d%d", &x, &y, &c);
        V[x].pb(mp(y, c));
        V[y].pb(mp(x, c));
    }

    Dijkstra(1);

    if(!p)
    {
        printf("%d\n", Dist[1][n]);
        return 0;
    }

    for(i = 0; i < p; i++)
        Dijkstra(P[i]);

    K = (1 << p) - 1;
    for(i = 1; i <= K; i++)
        for(j = 0; j < p; j++)
            dp[i][j] = INF;

    for(i = 0; i < p; i++)
        dp[1 << i][i] = Dist[1][P[i]];

    for(i = 1; i <= K; i++)
        for(j = 0; j < p; j++)
            if((1 << j) & i)
                for(k = 0; k < p; k++)
                    if(((1 << k) & i) && k != j)
                    {
                        aux = dp[i - (1 << j)][k] + Dist[P[j]][P[k]];
                        dp[i][j] = min(dp[i][j], aux);
                    }

    for(sol = INF, i = 0; i < p; i++)
        sol = min(sol, dp[K][i] + Dist[P[i]][n]);

    printf("%d\n", sol);

    return 0;
}