Cod sursa(job #1122824)

Utilizator andrici_cezarAndrici Cezar andrici_cezar Data 25 februarie 2014 20:38:40
Problema Ubuntzei Scor 100
Compilator cpp Status done
Runda Arhiva de probleme Marime 1.94 kb
#include <cstdio>
#include <vector>
#include <utility>
#include <queue>
#include <algorithm>
using namespace std;

int N, M, K, C[20], d[15][2001], cluj[2001];
int u, v, l;
int pd[1<<15][15];

vector< pair<int, int> > w[2010];

/* --- DIJKSTRA --- */

queue<int> q;
void initialize_unic_source( int nod, int d[] ) {
  for (int i = 1; i <= N; ++i) {
    d[i] = 1<<30;
  }
  d[nod] = 0;
}

void dijkstra( int nod, int d[] ) {
  initialize_unic_source( nod, d );

  for ( q.push(nod); !q.empty(); q.pop() ) {
    int u = q.front();

    for (int i = 0, l = w[u].size(); i < l; ++i) {
      int v = w[u][i].first,
          e = w[u][i].second;

      if ( d[u] + e < d[v] ) { // relax
        d[v] = d[u] + e;
        q.push(v);
      }
    }
  }
}

/* --- STOP DIJKSTRA --- */

inline bool isInConfig(int x, int no) {
  return (x&(1<<no)) != 0;
}

int main() {
  freopen("ubuntzei.in", "r", stdin);
  freopen("ubuntzei.out", "w", stdout);

  scanf("%d %d", &N, &M);
  scanf("%d", &K);

  for (int i = 0; i < K; ++i) {
    scanf("%d", &C[i]);
  }

  for (int i = 1; i <= M; ++i) {
    scanf("%d %d %d", &u, &v, &l);
    w[u].push_back( make_pair(v, l) );
    w[v].push_back( make_pair(u, l) );
  }

  dijkstra( 1, cluj );
  if ( K == 0 ) {
    printf("%d\n", cluj[N]);
    return 0;
  }
  for (int i = 0; i < K; ++i) {
    dijkstra( C[i], d[i] );
  }

  for (int i = 0, j; i < (1<<K); ++i) {
    for (j = 0; j < K; ++j) {
      if (i == (1<<j)) {
        break;
      }
    }

    if (i == (1<<j)) {
      pd[i][j] = cluj[ C[j] ];
      continue;
    }

    for (j = 0; j < K; ++j) {
      pd[i][j] = 1<<30;

      if ( !isInConfig(i, j) ) continue;

      for (int k = 0; k < K; ++k) {
        if ( !isInConfig(i, k) || k == j) continue;

        int cost = pd[i-(1<<j)][k] + d[k][ C[j] ];
        pd[i][j] = min( pd[i][j], cost );
      }

    }
  }

  int L = 1<<30;

  for (int i = 0; i < K; ++i) {
    L = min( L, pd[(1<<K)-1][i] + d[i][N] );
  }
  printf("%d\n", L);
  
  return 0;
}