Cod sursa(job #1087021)

Utilizator poptibiPop Tiberiu poptibi Data 18 ianuarie 2014 20:17:03
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.07 kb
#include <cstdio>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
using namespace std;

const int NMAX = 2010, KMAX = 15, INF = 0x3f3f3f3f;

int N, M, K, C[KMAX], Dist[KMAX][NMAX], Dp[1 << KMAX][KMAX], DistStart[NMAX];
vector<pair<int, int> > G[NMAX];
bool InQueue[NMAX];

void BF(int StartNode, int Dist[NMAX])
{
    for(int i = 1; i <= N; ++ i) Dist[i] = INF, InQueue[i] = 0;
    Dist[StartNode] = 0;
    queue<int> Q;
    Q.push(StartNode);

    while(!Q.empty())
    {
        int Node = Q.front();
        Q.pop();
        InQueue[Node] = 0;

        for(vector<pair<int, int> > :: iterator it = G[Node].begin(); it != G[Node].end(); ++ it)
        {
            int Vec = it -> first, Cost = it -> second;
            if(Dist[Vec] > Dist[Node] + Cost)
            {
                Dist[Vec] = Dist[Node] + Cost;
                if(!InQueue[Vec]) Q.push(Vec), InQueue[Vec] = 1;
            }
        }
    }
}

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

    scanf("%i %i %i", &N, &M, &K);
    for(int i = 0; i < K; ++ i) scanf("%i", &C[i]);
    for(int i = 1; i <= M; ++ i)
    {
        int X, Y, Z;
        scanf("%i %i %i", &X, &Y, &Z);
        G[X].push_back(make_pair(Y, Z));
        G[Y].push_back(make_pair(X, Z));
    }

    BF(1, DistStart);

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

    for(int i = 0; i < K; ++ i)
        BF(C[i], Dist[i]);

    memset(Dp, INF, sizeof(Dp));

    for(int i = 0; i < K; ++ i)
        Dp[1 << i][i] = DistStart[ C[i] ];

    for(int Conf = 1; Conf < (1 << K); ++ Conf)
        for(int i = 0; i < K; ++ i)
            if(Conf & (1 << i))
                for(int j = 0; j < K; ++ j)
                    if(i != j && Conf & (1 << j))
                        Dp[Conf][i] = min(Dp[Conf][i], Dp[Conf ^ (1 << i)][j] + Dist[j][ C[i] ]);

    int Ans = INF;
    for(int i = 0; i < K; ++ i)
        Ans = min(Ans, Dp[(1 << K) - 1][i] + Dist[i][N]);

    printf("%i\n", Ans);
}