Cod sursa(job #2937080)

Utilizator iraresmihaiiordache rares mihai iraresmihai Data 9 noiembrie 2022 21:13:48
Problema Ubuntzei Scor 70
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.7 kb
#include <iostream>
#include <vector>
#include <queue>

#define MAXK 15
#define MAXN 2000
#define MAXDIST 200000000
#define MAXMASK 131072
using namespace std;

struct edge{
  int b, cost;
};

struct node{
  int dist;
  bool visited;
  vector <edge> neighbours;
};

bool operator<(edge a, edge b) {
  return a.cost < b.cost;
}

priority_queue <edge> pq;
node graph[MAXN];
node graphWithGoodPos[MAXK];
int valuablePos[MAXK + 2];
long long dp[MAXK + 2][MAXMASK];

void addEdge(int a, int b, int cost) {
  graph[a].neighbours.push_back({b, cost});
  graph[b].neighbours.push_back({a, cost});
}

void addEdgeInGraphWithGoodPos(int a, int b, int cost) {
  graphWithGoodPos[a].neighbours.push_back({b, cost});
  graphWithGoodPos[b].neighbours.push_back({a, cost});
}

void dijkstra(int startPos, int n) {
  int i;
  edge pos;

  for ( i = 0; i < n; i++ ) {
    graph[i].dist = MAXDIST;
  }

  graph[startPos].dist = 0;
  for ( edge i2 : graph[startPos].neighbours ) {
    pq.push(i2);
  }

  while ( !pq.empty() ) {
    pos = pq.top();
    pq.pop();

    if ( graph[pos.b].dist > pos.cost ) {
      graph[pos.b].dist = pos.cost;
      for ( edge i2 : graph[pos.b].neighbours ) {
        if ( pos.cost + i2.cost < graph[i2.b].dist ) {
          pq.push({i2.b, pos.cost + i2.cost});
        }
      }
    }
  }
}

int main() {
  FILE *fin, *fout;
  fin = fopen("ubuntzei.in", "r");
  fout = fopen("ubuntzei.out", "w");

  int n, m, k, i, a, b, cost, i2;

  fscanf(fin, "%d%d%d", &n, &m, &k);

  valuablePos[0] = 0;
  for ( i = 1; i <= k; i++ ) {
    fscanf(fin, "%d", &valuablePos[i]);
    valuablePos[i]--;
  }
  valuablePos[k + 1] = n - 1;
  k += 2;

  for ( i = 0; i < m; i++ ) {
    fscanf(fin, "%d%d%d", &a, &b, &cost);
    a--;
    b--;

    addEdge(a, b, cost);
  }

  for ( i = 0; i < k; i++ ) {
    dijkstra(valuablePos[i], n);

    for ( i2 = i + 1; i2 < k; i2++ ) {
      //printf("%d %d %d\n", valuablePos[i] + 1, valuablePos[i2] + 1, graph[valuablePos[i2]].dist);
      addEdgeInGraphWithGoodPos(i, i2, graph[valuablePos[i2]].dist);
    }
  }

  for ( i = 0; i < (1 << k); i++ ) {
    for ( i2 = 0; i2 < k; i2++ ) {
      dp[i2][i] = (long long) MAXDIST * (MAXK + 2) + 1;
    }
  }

  dp[0][1] = 0;

  for ( i = 1; i < (1 << k); i++ ) {
    for ( i2 = 0; i2 < k; i2++ ) {
      if ( i & (1 << i2) ) {
        for ( edge i3 : graphWithGoodPos[i2].neighbours ) {
          if ( i & (1 << i3.b) ) {
            dp[i3.b][i] = min(dp[i3.b][i], (long long) dp[i2][i - (1 << i3.b)] + i3.cost);
          }
        }
      }
    }
  }

  fprintf(fout, "%lld\n", dp[k - 1][(1 << k) - 1]);

  fclose(fin);
  fclose(fout);

  return 0;
}