Cod sursa(job #1586172)

Utilizator BugirosRobert Bugiros Data 31 ianuarie 2016 20:39:59
Problema Ubuntzei Scor 85
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.01 kb
#define DEBUG
#include <fstream>
#include <vector>
#include <queue>
using namespace std;

const int MAXN = 2005;
const int MAXK = 17;
const int INF = 1 << 30;

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

int n;

vector<int> vecini[MAXN];
vector<int> cost[MAXN];

int special[MAXK];
int d[MAXN][MAXN];
int e[MAXK][1 << MAXK];
int k;

void citire()
{
    int m;
    in >> n >> m;
    in >> k;
    for (int i = 1;i <= k;++i)
        in >> special[i];
    for (int i = 1;i <= m;++i)
    {
        int x,y,c;
        in >> x >> y >> c;
        vecini[x].push_back(y);
        cost[x].push_back(c);

        vecini[y].push_back(x);
        cost[y].push_back(c);
    }
}

void dijkstra(int s)
{
    //initializare
    for (int i = 1;i <= n;++i)
        d[s][i] = INF;
    priority_queue< pair<int,int>,vector< pair<int,int> >, greater< pair<int,int> > > heap;
    heap.push(make_pair(0,s));
    while(!heap.empty())
    {
        int nod = heap.top().second;
        int c = heap.top().first;
        heap.pop();
        if (d[s][nod] != INF)
            continue;
        d[s][nod] = c;
        for (unsigned int i = 0;i < vecini[nod].size();++i)
            heap.push(make_pair(d[s][nod] + cost[nod][i],
                                vecini[nod][i]));
    }
}

void calculare_distante()
{
    //calculare d
    dijkstra(1);
    dijkstra(n);
    for (int i = 1;i <= k;++i)
        dijkstra(special[i]);
}

int S;

int sol[MAXK];

int nrbiti(int nr)
{
    int rasp = 0;
    while(nr != 0)
    {
        if ((nr & 1) != 0)
            ++rasp;
        nr >>= 1;
    }
    return rasp;
}

void prelucrare()
{
    if (nrbiti(S) == 1)
        return;

    for (int u = 1;u <= k;++u)
    {
        e[u][S] = INF;
        if ((S & (1 << u)) == 0)
            continue;
        for (int v = 1;v <= k;++v)
            if(v != u && (S & (1 << v)) != 0)
            {
                int nr = e[v][S - (1 << u)] + d[special[v]][special[u]];
                if (nr < e[u][S])
                    e[u][S] = nr;
            }
    }
}

void dinamica()
{
    //initializare
    for (int i = 1;i <= k;++i)
        e[i][1 << i] = d[1][special[i]];

    for (int s = 1;s < (1 << k);++s)
    {
        S = s << 1;
        prelucrare();
    }
}

void afisare()
{
    if (k == 0)
    {
        out << d[1][n] << '\n';
        return;
    }

    S = ((1 << k) - 1) << 1;

    int raspuns = INF;
    for (int u = 1;u <= k;++u)
    {
        int nr = e[u][S] + d[special[u]][n];
        if (nr < raspuns)
            raspuns = nr;
    }
    out << raspuns << '\n';
}

int main()
{
    citire();
    calculare_distante();

    #ifdef DEBUG
    for (int i = 1;i <= n;++i)
        printf("%u ",vecini[i].size());
    printf("\n\n");
    for (int i = 1;i <= n;++i)
    {
        for (int j = 1;j <= n;++j)
            printf("%d ",d[i][j]);
        printf("\n");
    }
    #endif // DEBUG

    dinamica();
    afisare();

    return 0;
}