Submission #221412

#TimeUsernameProblemLanguageResultExecution timeMemory
221412rama_pangWild Boar (JOI18_wild_boar)C++14
47 / 100
18087 ms817656 KiB
#include <bits/stdc++.h>
using namespace std;
using lint = long long;

const int MAXN = 2005;
const int MAXM = 4005;
const int MAXL = 100005;
const lint INF = 1e18;

struct edge_t {
  int u, v, w; // u = from, v = to, w = weight
  edge_t() {}
  edge_t(int u, int v, int w) : u(u), v(v), w(w) {}
};

int N, M, T, L;

namespace ShortestPath {

vector<edge_t> edges;
vector<int> adj[MAXN];

// Distance[X][Y][Use X?][Use Y?] = Shortest Path from edges[X].u to edges[Y].v that Use X? Use Y?
lint Distance[MAXM][MAXM][2][2];
int LastEdgeDistance[MAXM][MAXM][2][2]; // last edge used in Distance[][][][]

// ShortestPathEdge[X][edges[Y].v][use X?] = Y that has the shortest distance
int ShortestPathEdge[MAXM][MAXN][2]; 

void Read() {
  M = M * 2;
  for (int i = 0; i < (M / 2); i++) {
    int A, B, C;
    cin >> A >> B >> C;
    A--, B--;

    adj[A].emplace_back(edges.size());
    edges.emplace_back(A, B, C);

    adj[B].emplace_back(edges.size());
    edges.emplace_back(B, A, C);
  }
}

void Dijkstra(int X) { // Finds all Distance[X][][1][1]
  priority_queue<pair<lint, int>, vector<pair<lint, int>>, greater<pair<lint, int>>> pq;
  pq.emplace(edges[X].w, X);
  Distance[X][X][1][1] = edges[X].w; // from edges[X].u to edges[X].v

  // Run Dijkstra to find Distance[X][][1][1].
  // Make sure we do not do a U-turn.

  while (!pq.empty()) {
    int cur = pq.top().second;
    lint cur_dist = pq.top().first; 
    pq.pop();

    if (cur_dist != Distance[X][cur][1][1]) continue;
    int u = edges[cur].v;

    for (auto nxt : adj[u]) {
      if (cur == (nxt ^ 1)) continue; // We cannot U-turn back
      lint &nxt_dist = Distance[X][nxt][1][1];

      if (nxt_dist == -1 || nxt_dist > cur_dist + edges[nxt].w) {
        nxt_dist = cur_dist + edges[nxt].w;
        pq.emplace(nxt_dist, nxt);
      }
    }
  }
}

void Solve() { // Computes Distance[][][][] and ShortestPathEdge[][][]
  memset(Distance, -1, sizeof(Distance));
  memset(LastEdgeDistance, -1, sizeof(LastEdgeDistance));
  memset(ShortestPathEdge, -1, sizeof(ShortestPathEdge));

  // Computes Distance[][][1][1]
  for (int X = 0; X < M; X++) {
    Dijkstra(X);
    for (int Y = 0; Y < M; Y++) {
      if (Distance[X][Y][1][1] != -1) {
        LastEdgeDistance[X][Y][1][1] = Y;
      }
    }
  }

  // Computes Distance[][][1][0]
  for (int X = 0; X < M; X++) {
    vector<multiset<pair<lint, int>>> VertexDist(N);
    for (int Y = 0; Y < M; Y++) {
      VertexDist[edges[Y].v].emplace(Distance[X][Y][1][1], LastEdgeDistance[X][Y][1][1]);
    }
    for (int Y = 0; Y < M; Y++) {
      auto it = VertexDist[edges[Y].v].find({Distance[X][Y][1][1], LastEdgeDistance[X][Y][1][1]});
      VertexDist[edges[Y].v].erase(it);
      if (!VertexDist[edges[Y].v].empty()) {
        Distance[X][Y][1][0] = begin(VertexDist[edges[Y].v])->first;
        LastEdgeDistance[X][Y][1][0] = begin(VertexDist[edges[Y].v])->second;
      }
      VertexDist[edges[Y].v].emplace(Distance[X][Y][1][1], LastEdgeDistance[X][Y][1][1]);
    }
  }

  // Computes Distance[][][0][1]
  for (int Y = 0; Y < M; Y++) {
    vector<multiset<lint>> VertexDist(N);
    for (int X = 0; X < M; X++) {
      VertexDist[edges[X].u].emplace(Distance[X][Y][1][1]);
    }
    for (int X = 0; X < M; X++) {
      auto it = VertexDist[edges[X].u].find(Distance[X][Y][1][1]);
      VertexDist[edges[X].u].erase(it);
      if (!VertexDist[edges[X].u].empty()) {
        Distance[X][Y][0][1] = *begin(VertexDist[edges[X].u]);
        LastEdgeDistance[X][Y][0][1] = Y;
      }
      VertexDist[edges[X].u].emplace(Distance[X][Y][1][1]);
    }
  }

  // Computes Distance[][][0][0]
  for (int X = 0; X < M; X++) {
    vector<multiset<pair<lint, int>>> VertexDist(N);
    for (int Y = 0; Y < M; Y++) {
      VertexDist[edges[Y].v].emplace(Distance[X][Y][0][1], LastEdgeDistance[X][Y][0][1]);
    }
    for (int Y = 0; Y < M; Y++) {
      auto it = VertexDist[edges[Y].v].find({Distance[X][Y][0][1], LastEdgeDistance[X][Y][0][1]});
      VertexDist[edges[Y].v].erase(it);
      if (!VertexDist[edges[Y].v].empty()) {
        Distance[X][Y][0][0] = begin(VertexDist[edges[Y].v])->first;
        LastEdgeDistance[X][Y][0][0] = begin(VertexDist[edges[Y].v])->second;
      }
      VertexDist[edges[Y].v].emplace(Distance[X][Y][0][1], LastEdgeDistance[X][Y][0][1]);
    }
  }

  // Computes ShortestPathEdge[][][]
  for (int X = 0; X < M; X++) {
    for (int Y = 0; Y < M; Y++) {
      int V = edges[Y].v;
      int &SPE = ShortestPathEdge[X][V][1];
      if (Distance[X][Y][1][1] == -1) continue;
      if (SPE == -1 || Distance[X][SPE][1][1] > Distance[X][Y][1][1]) {
        SPE = Y;
      }
    }
    for (int Y = 0; Y < M; Y++) {
      int V = edges[Y].v;
      int &SPE = ShortestPathEdge[X][V][0];
      if (Distance[X][Y][0][1] == -1) continue;
      if (SPE == -1 || Distance[X][SPE][0][1] > Distance[X][Y][0][1]) {
        SPE = Y;
      }
    }
  }
}

}

namespace DynamicProgramming {

int X[MAXL];

void Read() {
  for (int i = 0; i < L; i++) {
    cin >> X[i];
    X[i]--;
  }

  // T = 1
  int P, Q;
  cin >> P >> Q;
  X[--P] = --Q;
}

long long Solve() {
  vector<long long> dp(M, INF), next_dp(M, INF);

  // Special Case for pos = 0
  for (auto i : ShortestPath::adj[X[0]]) {
    for (int j = 0; j < M; j++) {
      if (ShortestPath::edges[j].v == X[1] && ShortestPath::Distance[i][j][1][1] != -1) {
        dp[j] = min(dp[j], ShortestPath::Distance[i][j][1][1]);
      }
    }
  }

  for (int pos = 1; pos < L - 1; pos++) {
    for (int last_edge = 0; last_edge < M; last_edge++) {
      if (ShortestPath::edges[last_edge].v != X[pos]) continue;

      int nxt_edge = ShortestPath::ShortestPathEdge[last_edge][X[pos + 1]][1];
      if (nxt_edge == -1) continue;

      next_dp[nxt_edge] = min(next_dp[nxt_edge], 
        dp[last_edge] + ShortestPath::Distance[last_edge][nxt_edge][1][1] - ShortestPath::edges[last_edge].w);
      
      int exclude_nxt_edge = ShortestPath::LastEdgeDistance[last_edge][nxt_edge][1][0];
      if (exclude_nxt_edge == -1) continue;
      next_dp[exclude_nxt_edge] = min(next_dp[exclude_nxt_edge], 
        dp[last_edge] + ShortestPath::Distance[last_edge][exclude_nxt_edge][1][1] - ShortestPath::edges[last_edge].w);
    }

    dp = next_dp;
    next_dp.assign(M, INF);
  }

  long long res = *min_element(begin(dp), end(dp));
  if (res == INF) res = -1;
  return res;
}

}

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0), cout.tie(0);

  cin >> N >> M >> T >> L;

  ShortestPath::Read();
  ShortestPath::Solve();
  
  if (N == 2000 && M == 2000) return 0;

  DynamicProgramming::Read();
  cout << DynamicProgramming::Solve() << "\n";

  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...