Cod sursa(job #2758353)

Utilizator Alex_tz307Lorintz Alexandru Alex_tz307 Data 9 iunie 2021 22:15:44
Problema Team Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.02 kb
#include <bits/stdc++.h>
#define INF 0x3f3f3f3f

using namespace std;

ifstream fin("team.in");
ofstream fout("team.out");

const int MAXN = 500;
const int MAXP = 50;
vector<pair<int,int>> G[1 + MAXN];
int dist[1 + MAXP][1 + MAXN], dp[1 + MAXP][1 + MAXP][1 + MAXP];
/// dp[i][j][k] - costul minim pentru a aduce la destinatie persoanele din intervalul i...j, considerand ca acestea pleaca de la destinatia persoanei k
/// Cum pot ajunge la asta?
/// Observi ca daca duci o persoana la destinatia sa, grupul se imparte in doua, deci acea persoana e un split point, deci de aici te poti gandi la range dp(O(p^3) pana aici)
/// Nu sti in ce ordine sa parcurgi graful pentru a lasa persoane la destinatii si obtine si solutie optima, p e mic, deci mai poti adauga o stare la dinamica care sa zica din ce sediu vrei sa pleci mai departe cu un grup(pentru ca mereu ai nevoie de rezultatelee grupurilor mai mici pentru a calcula un grup mare se deduce usor ca dinamica trebuie calculata bottom-up(intervalele mai mici primele)) => O(p^4)
/// => Raspunsul este dp[0][p - 1][0](plec cu tot grupul din prima statie)
/// Obs: persoanele adiacente(adica cu indici consecutivi) care au aceeasi destinatie pot fi transformate intr-o singura persoana, pentru ca mereu va fi optim sa le las la destinatie pe toate in acelasi timp

void min_self(int &x, int y) {
  x = min(x, y);
}

int main() {
  int p, n, m;
  fin >> p >> n >> m;
  for (int i = 0; i < m; ++i) {
    int u, v, w;
    fin >> u >> v >> w;
    G[u].emplace_back(v, w);
    G[v].emplace_back(u, w);
  }
  vector<int> sources;
  int k = 0;
  for (int i = 0; i <= p; ++i) {
    int nod;
    if (i == 0)
      nod = 1;
    else fin >> nod;
    if (sources.empty() || nod != sources.back()) {
      priority_queue<pair<int,int>, vector<pair<int,int>>, greater<pair<int,int>>> pq;
      for (int v = 1; v <= n; ++v)
        dist[k][v] = INF;
      dist[k][nod] = 0;
      pq.emplace(0, nod);
      while (0 < pq.size()) {
        int d, u;
        tie(d, u) = pq.top();
        pq.pop();
        if (d != dist[k][u])
          continue;
        for (auto it : G[u]) {
          int v, w;
          tie(v, w) = it;
          int cost = d + w;
          if (dist[k][v] > cost) {
            dist[k][v] = cost;
            pq.emplace(dist[k][v], v);
          }
        }
      }
      sources.emplace_back(nod);
      k = sources.size();
    }
  }
  p = k;
  for (int i = 0; i < p; ++i)
    for (int j = i; j < p; ++j)
      for (int k = 0; k < p; ++k)
        dp[i][j][k] = INF;
  for (int lg = 1; lg <= p; ++lg)
    for (int i = 0; i + lg - 1 < p; ++i) {
      int j = i + lg - 1;
      for (int k = i; k <= j; ++k)
        for (int t = 0; t < p; ++t) {
          int best = dist[t][sources[k]];
          if (i <= k - 1)
            best += dp[i][k - 1][k];
          if (k + 1 <= j)
            best += dp[k + 1][j][k];
          min_self(dp[i][j][t], best);
        }
    }
  fout << dp[0][p - 1][0] << '\n';
  fin.close();
  fout.close();
  return 0;
}