Cod sursa(job #637597)

Utilizator Bit_MasterAlexandru-Iancu Caragicu Bit_Master Data 20 noiembrie 2011 15:27:46
Problema Ubuntzei Scor 80
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.11 kb
// priority_queue<T, vector<T>, greater<T> > heap;
/*lant hamiltonian pe graf format numai din nodurile cu prieteni si 1 si n, cu muchii egale cu distantele dintre
ele preprocesate cu dijkstra
+
dinamica [submultime][nod_final_submultime] -> dinamica[submultime + nod_nou][nod_nou]
pt fiecare submultime de elem conteaza numai costul minim dintre ele (costurile pt drumurile dintre celelalte noduri
                                                                      nu depind de cele existente in submultime)
*/
#include <cstdio>
#include <queue>
#include <algorithm>
using namespace std;

const int INF = 1000000000;

const int N = 2012;
const int K = 17;

struct destinatie
{
    int dest,cost;
};

priority_queue < pair <int,int>, vector < pair<int,int> >, greater< pair<int,int> > > heap;
vector< destinatie > vecin[N]; int n; int d[N];
int noduri_k[K],k;

int a[1<<(K-2)][K]; //dinamica pe submultimi si elem final din submultime

int graf[K][K];

void citire()
{
    int m;
    int a,b,c;
    scanf("%d%d",&n,&m);
    scanf("%d",&k);

    noduri_k[0] = 1;
    for (int i = 1;i <= k; ++i)
        scanf("%d",&noduri_k[i]);
    noduri_k[k+1] = n;

    for (int i = 1; i <= m; ++i)
    {
        scanf("%d%d%d",&a,&b,&c);
        vecin[a].push_back((destinatie){b,c});
        vecin[b].push_back((destinatie){a,c});
    }
}

void init_dijkstra()
{
    for (int i = 1; i <= n; ++i)
            d[i] = INF;
}

void dijkstra(int nod_start)
{
    int nod,c;
    init_dijkstra();
    heap.push(make_pair(0,nod_start));
    while (!heap.empty())
    {
        nod = heap.top().second;
        c = heap.top().first;
        heap.pop();
        if (d[nod] != INF)
            continue;
        d[nod] = c;
        for (unsigned int i = 0; i < vecin[nod].size(); ++i)
            if (d[vecin[nod][i].dest] == INF)
                heap.push(make_pair(c+vecin[nod][i].cost,vecin[nod][i].dest));
    }
}

void dinamica()         //identific submultime prin cifrele in baza 2 ale indicelui, cifra 0 indica daca exista nodul k 1, 1 nodul k 2 ...
{
    int in,jn;
    for (int i = 1; i <= (1<<k) - 1; ++i)
        for (int j = 0; j <= k-1; ++j)
            {
                if ((i & (1<<j)) == 0)   //i & (1<<j) == 1<<j daca contine cifra
                    continue;
                if ((i & (i-1)) == 0)
                {
                    a[i][j] = graf[0][j+1];
                    continue;
                }
                //elimin ultimul nod din config (nodul j) si dau for pt cine a fost ultimul nod
                in = i - (1<<j);
                a[i][j] = INF;
                for (jn = 0; jn <= k-1; ++jn)
                    if ((in & (1<<jn)) != 0)
                        a[i][j] = min(a[i][j],a[in][jn] + graf[jn+1][j+1]);
            }
    int rasp = INF;
    for (int j = 0; j <= k-1; ++j)
        rasp = min(rasp,a[(1<<k) - 1][j] + graf[j+1][k+1]);
    printf("%d\n",rasp);
}

int main()
{
    freopen("ubuntzei.in","r",stdin);
    freopen("ubuntzei.out","w",stdout);
    citire();
    for (int i = 0; i <= k+1; ++i)
    {
        dijkstra(noduri_k[i]);
        for (int j = 0; j <= k+1; ++j)
            graf[i][j] = d[noduri_k[j]];
    }
    dinamica();
    return 0;
}