Cod sursa(job #1944240)

Utilizator TimoteiCopaciu Timotei Timotei Data 29 martie 2017 00:49:14
Problema Ubuntzei Scor 70
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.29 kb
#include <iostream>
#include <fstream>
#include <vector>
#include <queue>
#define nMax 2005
#define mMax 10005
#define inf 1 << 30
using namespace std;
// c[i][j] - dist minima dintre nodul i si j din k
// dp[i][j] - distanta minima a unui laant ce se termina cu j si trece
// prin nodurile date de pozitiile cifrelor de 1 in configuratia binara a lui i
int n, m, K, dist[nMax], c[19][19], dp[1 << 17][19], k[19];
typedef struct {
  int nod, cost;
} muchie;
muchie h;
vector <muchie> v[nMax];
queue <int> C;
void read()
{
    ifstream fin("ubuntzei.in");
    fin >> n >> m >> K;
    int x;
    for(int i = 1; i <= K; ++i)
        fin >> k[i];
    k[K + 1] = n;
    k[0] = 1;
    for(int i = 1; i <= m; ++i){
        fin >> x >> h.nod >> h.cost;
        v[x].push_back(h);
        swap(x, h.nod);
        v[x].push_back(h);
    }
}
void dijkstra(int nod, int index)
{
    for(int i = 0; i <= K + 1; ++i)
        c[index][i] = inf;
    c[index][index] = 0;
    int x, y;
    for(int i = 1; i <= n; ++i)
        dist[i] = inf;
    C.push(nod);
    dist[nod] = 0;
    while(!C.empty()){
      x = C.front();
      C.pop();
      for(int i = 0; i < v[x].size(); ++i){
        y = v[x][i].nod;
        if(dist[x] + v[x][i].cost < dist[y]){
            dist[y] = dist[x] + v[x][i].cost;
            C.push(y);
        }
      }
    }
   for(int i = 0; i <= K + 1; ++i)
       c[index][i] = min(c[index][i], dist[k[i]]);
}
void solve()
{
    for(int i = 0; i <= K + 1; ++i)
        dijkstra(k[i], i);  // calculez distantele de la al i-lea nod din la toate celelalte noduri din k
    // calculam un ciclu hamiltonian format doar din cele K + 1 noduri din k
    K += 2;
    for(int i = 1; i < (1 << K); ++i)
      for(int j = 0; j < K; ++j)
         dp[i][j] = inf;
    dp[1][0] = 0;
    for(int i = 1; i < (1 << K); ++i)
        for(int j = 0; j < K; ++j)
         if(i & (1 << j)) // daca j face parte din lantul i
            for(int h = 0; h < K; ++h)
               if(c[h][j] != inf && i & (1 << h)) // daca exista drum intre h si j si daca h face parte din lantul i
                  dp[i][j] = min(dp[i][j], dp[i ^ (1 << j)][h] + c[h][j]);
    ofstream fout("ubuntzei.out");
    fout << dp[(1 << K) - 1][K - 1];
}
int main()
{
    read();
    solve();
    return 0;
}