Cod sursa(job #2170599)

Utilizator stoianmihailStoian Mihail stoianmihail Data 15 martie 2018 08:52:59
Problema Ubuntzei Scor 50
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <stdio.h>
#include <queue>
#include <vector>
#include <climits>

using std::priority_queue;
using std::vector;

const long long INF = LLONG_MAX / 3;

struct cell {
  long long cost;
  int u;

  cell() {
    this -> cost = 0;
    this -> u = 0;
  }

  cell(int u, long long cost) {
    this -> cost = cost;
    this -> u = u;
  }
};

typedef struct {
  bool operator()(const cell &X, const cell &Y) {
    return X.cost > Y.cost;
  }
} minHeap;

priority_queue <cell, vector <cell>, minHeap> heap;

#define MAX_N 2005
#define MAX_M 10005
#define MAX_C 20

typedef struct {
  int v, cost, next;
} list;

int N, M, K;
int adj[MAX_N];
list l[2 * MAX_M];
long long d[MAX_N];
long long save[MAX_C][MAX_C];
int ss, stack[MAX_C];
int u[MAX_C];
long long attain;
long long min = INF;
char seen[MAX_N];

void addEdge(int u, int v, int cost, int pos) {
  l[pos].v = v;
  l[pos].cost = cost;
  l[pos].next = adj[u];
  adj[u] = pos;
}

void init() {
  int u;
  for (u = 1; u <= N; u++) {
    d[u] = INF;
  }
}

void dijkstra(int u) {
  init();

  heap.push(cell(u, 0));
  d[u] = 0;

  long long cost, now;
  int v, pos;
  cell curr;
  while (!heap.empty()) {
    curr = heap.top();
    heap.pop();

    cost = curr.cost;
    u = curr.u;

    if (cost == d[u]) {
      for (pos = adj[u]; pos; pos = l[pos].next) {
        v = l[pos].v;
        now = cost + l[pos].cost;

        if (now < d[v]) {
          d[v] = now;
          heap.push(cell(v, now));
        }
      }
    }
  }
}

void print() {
  for (int i = 1; i <= N; i++) {
    fprintf(stderr, "%d ", d[i]);
  }
  fprintf(stderr, "\n");
}

void fill(int pos) {
  int i;
  for (i = 0; i <= K; i++) {
    save[pos][i] = d[u[i]];
  }
}

void bkt(int pos) {
  if (attain > min) {
    return;
  }
  // imbunatatire daca depaseste minimul deja
  if (pos == K - 1) {
    //fprintf(stderr, "ajunge\n");
    if (attain + save[K][stack[ss - 1]] < min) {
      min = attain + save[K][stack[ss - 1]];
    }
    return;
  }

  //fprintf(stderr, "%d -> %d\n", pos, stack[ss - 1]);

  int i;
  for (i = 1; i <= K - 1; i++) {
    if (seen[i] == 0) {
      seen[i] = 1;
      attain += save[stack[ss - 1]][i];
      stack[ss++] = i;

      bkt(pos + 1);

      ss--;
      seen[i] = 0;
      attain -= save[stack[ss - 1]][i];
    }
  }
}

int main(void) {
  FILE *f = fopen("ubuntzei.in", "r");

  int i;
  fscanf(f, "%d %d %d", &N, &M, &K);
  for (i = 1; i <= K; i++) {
    fscanf(f, "%d", &u[i]);
   // yes[u[i]] = 1;
  }

  /*
  yes[1] = 1;
  yes[N] = 1;

  for (i = 1; i <= N; i++) {
    yes[i] += yes[i - 1];
  }*/

  int us, v, cost;
  for (i = 1; i <= M; i++) {
    fscanf(f, "%d %d %d", &us, &v, &cost);
    addEdge(us, v, cost, i);
    addEdge(v, us, cost, i + M);
  }
  fclose(f);

  u[0] = 1;
  u[K + 1] = N;
  K++;
  for (i = 0; i <= K; i++) {
    dijkstra(u[i]);
    //print();
    fill(i);
  }
/*
  fprintf(stderr, "%d\n", K);

  for (i = 0; i <= K; i++) {
    for (int j = 0; j <= K; j++) {
      fprintf(stderr, "%lld ", save[i][j]);
    }
    fprintf(stderr,"\n");
  }
*/
  stack[ss++] = 0;
  bkt(0);

  freopen("ubuntzei.out", "w", stdout);
  fprintf(stdout, "%lld\n", min);
  fclose(stdout);
  return 0;
}