Cod sursa(job #1943294)

Utilizator PaulStighiStiegelbauer Paul-Alexandru PaulStighi Data 28 martie 2017 14:55:40
Problema Ubuntzei Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.3 kb
#include <fstream>
#include <iostream>
#include <vector>
using namespace std;

ifstream fin("ubuntzei.in");
ofstream fout("ubuntzei.out");

const int NMax = 2005;
const int KMax = 17;
const int oo = 1<<30;

struct Muchie
{
    int v,c;
};

int N,M,K,NHeap,Conf,Sol = oo;
int C[KMax],Dist[NMax],Heap[NMax],Poz[NMax],DP[1 << KMax][NMax];

vector <Muchie> G[NMax],H[KMax];

void Read()
{
    fin>>N>>M>>K;

    for(int i = 1 ; i <= K ; ++i)
        fin>>C[i];

    C[0] = 1;   C[K+1] = N;   K += 2;

    for(int i = 1 ; i <= M ; ++i)
    {
        int x,y,z;  fin>>x>>y>>z;
        Muchie M;   M.c = z;
        M.v = y;    G[x].push_back(M);
        M.v = x;    G[y].push_back(M);
    }
}

void UpHeap(int Nod)
{
    int Tata = Nod >> 1;

    if(Tata > 0 && Dist[Heap[Tata]] > Dist[Heap[Nod]])
    {
        swap(Heap[Tata],Heap[Nod]);
        swap(Poz[Heap[Tata]],Poz[Heap[Nod]]);
        UpHeap(Tata);
    }
}

void DownHeap(int Nod)
{
    int Fiu = Nod << 1;

    if(Fiu + 1 <= NHeap && Dist[Heap[Fiu]] > Dist[Heap[Fiu + 1]])
        Fiu++;

    if(Fiu <= NHeap && Dist[Heap[Fiu]] < Dist[Heap[Nod]])
    {
        swap(Heap[Fiu],Heap[Nod]);
        swap(Poz[Heap[Fiu]],Poz[Heap[Nod]]);
        DownHeap(Fiu);
    }
}

void Dijkstra(int Nod)
{
    for(int i = 1 ; i <= N; ++i)
        Dist[i] = oo;

    Heap[1] = Nod;
    Poz[Nod] = 1;
    Dist[Nod] = 0;
    NHeap = 1;

    while(NHeap)
    {
        int nod = Heap[1];
        swap(Heap[1],Heap[NHeap]);
        swap(Poz[Heap[1]],Poz[Heap[NHeap]]);
        Heap[NHeap] = Poz[Heap[NHeap]] = 0;
        NHeap--;    DownHeap(1);

        for(int i = 0 ; i < (int) G[nod].size() ; ++i)
        {
            int Vecin = G[nod][i].v;
            int Cost = G[nod][i].c;

            if(Dist[Vecin] == oo)
            {
                Heap[++NHeap] = Vecin;
                Poz[Vecin] = NHeap;
                UpHeap(NHeap);
            }

            if(Dist[Vecin] > Dist[nod] + Cost)
            {
                Dist[Vecin] = Dist[nod] + Cost;
                UpHeap(Poz[Vecin]);
            }
        }
    }
}

void Solve()
{
    for(int i = 0 ; i < K ; ++i)
    {
        int Nod = C[i];
        Dijkstra(Nod);

        for(int j = 0 ; j < K ; ++j)
        {
            int Vecin = C[j];
            int Cost = Dist[Vecin];

            if(Nod != Vecin && Cost != oo)
            {
                Muchie M;   M.v = j;    M.c = Cost;
                H[i].push_back(M);
            }
        }
    }

    Conf = 1 << K;

    for(int i = 0 ; i < Conf ; ++i)
        for(int j = 0 ; j < K ; ++j)
            DP[i][j] = oo;

    DP[1][0] = 0;

    for(int i = 1 ; i < Conf ; ++i)
        for(int j = 0 ; j < K ; ++j)
            if(i & (1 << j))
            {
                for(int k = 0 ; k < (int) H[j].size() ; ++k)
                {
                    int Vecin = H[j][k].v;
                    int Cost = H[j][k].c;

                    if(i && (1 << Vecin))
                        DP[i][j] = min(DP[i][j] , DP[i - (1 << j)][Vecin] + Cost);
                }
            }

    Sol = DP[Conf - 1][K-1];
}

void Print()
{
    fout<<Sol<<"\n";
}

int main()
{
    Read();
    Solve();
    Print();

    fin.close();
    fout.close();
    return 0;
}