Cod sursa(job #1586180)

Utilizator BugirosRobert Bugiros Data 31 ianuarie 2016 20:45:17
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.79 kb
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;

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

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()
{
    freopen("ubuntzei.in","r",stdin);
    freopen("ubuntzei.out","w",stdout);
    int m;
    scanf("%d%d",&n,&m);
    scanf("%d",&k);
    for (int i = 1;i <= k;++i)
        scanf("%d",&special[i]);
    for (int i = 1;i <= m;++i)
    {
        int x,y,c;
        scanf("%d%d%d",&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);
    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)
    if (__builtin_popcount(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)
    {
        printf("%d\n",d[1][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;
    }
    printf("%d\n",raspuns);
}

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

    dinamica();
    afisare();

    return 0;
}