Problem p00270 (C++) — buggy submission, verdict: Memory Limit Exceeded


#include <bits/stdc++.h>
using namespace std;

struct Edge {
  int from, to, weight;
};
struct Query {
  int from, to;
};

vector<int> Dijkstra(const vector<vector<Edge>> &edge, const int start,
                     const int goal) {
  typedef tuple<int, int> Node;
  const int INF = INT_MAX >> 1;

  vector<int> cost(edge.size(), INF);
  priority_queue<Node, vector<Node>, greater<Node>> q;
  q.emplace(0, start);
  while (!q.empty()) {
    int c, v;
    tie(c, v) = q.top();
    q.pop();
    if (cost[v] != INF)
      continue;
    cost[v] = c;
    if (v == goal)
      break;
    for (const auto &e : edge[v])
      if (cost[e.to] == INF)
        q.emplace(c + e.weight, e.to);
  }
  return cost;
}

vector<vector<int>> optimize(const vector<vector<Edge>> &edge,
                             const vector<int> &cost, const int start,
                             const int goal) {
  vector<vector<int>> outedge(edge.size());
  vector<vector<int>> inedge(edge.size());
  for (const auto &list : edge)
    for (const auto &e : list) {
      if (cost[e.from] + e.weight > cost[e.to])
        continue;
      outedge[e.from].push_back(e.to);
      inedge[e.to].push_back(e.from);
    }

  typedef tuple<int, int> Node;
  priority_queue<Node, vector<Node>, greater<Node>> q;
  for (int v = 0; v < edge.size(); ++v)
    q.emplace(outedge[v].size(), v);
  vector<bool> visited(edge.size(), false);
  while (!q.empty()) {
    int outdegree, v;
    tie(outdegree, v) = q.top();
    q.pop();
    if (outdegree)
      break;
    if (visited[v])
      continue;
    visited[v] = true;
    if (v == start || v == goal)
      continue;
    for (const auto &i : inedge[v]) {
      outedge[i].erase(find(
          outedge[i].begin(), outedge[i].end(),
          v)); // →
               // ここではフラグだけ付けておいて、後で構築しなおしたほうが早いかもしれない
      q.emplace(outedge[i].size(), i);
    }
  }
  return outedge;
}

void dfs(const vector<vector<int>> &edge, const int v, vector<bool> &visited,
         vector<int> &order) {
  if (visited[v])
    return;
  visited[v] = true;
  for (const auto &to : edge[v])
    dfs(edge, to, visited, order);
  order.push_back(v);
}

vector<int> topological_sort(const vector<vector<int>> &edge, const int start,
                             const int goal) {
  vector<int> order;
  vector<bool> visited(edge.size(), false);
  dfs(edge, start, visited, order);
  reverse(order.begin(), order.end());
  return order;
}

int main() {
  int S, R;
  cin >> S >> R;

  vector<vector<Edge>> edge(S);
  for (int i = 0; i < R; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    edge[u].push_back({u, v, w});
    edge[v].push_back({v, u, w});
  }

  int a, b;
  cin >> a >> b;
  --a;
  --b;

  int Q;
  cin >> Q;
  vector<Query> query;
  for (int i = 0; i < Q; ++i) {
    int c, d;
    cin >> c >> d;
    query.push_back({--c, --d});
  }

  auto cost = Dijkstra(edge, a, b);
  auto optimized_edge = optimize(edge, cost, a, b);
  auto order = topological_sort(optimized_edge, a, b);

  const int BIT = 64;
  for (int i = 0; i < Q; i += BIT) {
    vector<bitset<BIT>> dp(S);
    for (int j = 0; j < BIT && i + j < Q; ++j)
      dp[query[i + j].from].set(j);
    for (const auto &from : order)
      for (const auto &to : optimized_edge[from])
        dp[to] = dp[to] | dp[from];
    for (int j = 0; j < BIT && i + j < Q; ++j)
      cout << (dp[query[i + j].to].test(j) ? "Yes" : "No") << endl;
  }
}

Error: MLE

Fixed submission:


#include <bits/stdc++.h>
using namespace std;

struct Edge {
  int from, to, weight;
};
struct Query {
  int from, to;
};

vector<int> Dijkstra(const vector<vector<Edge>> &edge, const int start,
                     const int goal) {
  typedef tuple<int, int> Node;
  const int INF = INT_MAX >> 1;

  vector<int> cost(edge.size(), INF);
  priority_queue<Node, vector<Node>, greater<Node>> q;
  q.emplace(0, start);
  while (!q.empty()) {
    int c, v;
    tie(c, v) = q.top();
    q.pop();
    if (c > cost[goal])
      break;
    if (c > cost[v])
      continue;
    cost[v] = c;
    for (const auto &e : edge[v])
      q.emplace(c + e.weight, e.to);
  }
  return cost;
}

vector<vector<int>> optimize(const vector<vector<Edge>> &edge,
                             const vector<int> &cost, const int start,
                             const int goal) {
  vector<vector<int>> outedge(edge.size());
  vector<vector<int>> inedge(edge.size());
  for (const auto &list : edge)
    for (const auto &e : list) {
      if (cost[e.from] + e.weight > cost[e.to])
        continue;
      outedge[e.from].push_back(e.to);
      inedge[e.to].push_back(e.from);
    }

  typedef tuple<int, int> Node;
  priority_queue<Node, vector<Node>, greater<Node>> q;
  for (int v = 0; v < edge.size(); ++v)
    q.emplace(outedge[v].size(), v);
  vector<bool> visited(edge.size(), false);
  while (!q.empty()) {
    int outdegree, v;
    tie(outdegree, v) = q.top();
    q.pop();
    if (outdegree)
      break;
    if (visited[v])
      continue;
    visited[v] = true;
    if (v == start || v == goal)
      continue;
    for (const auto &i : inedge[v]) {
      outedge[i].erase(find(
          outedge[i].begin(), outedge[i].end(),
          v)); // →
               // ここではフラグだけ付けておいて、後で構築しなおしたほうが早いかもしれない
      q.emplace(outedge[i].size(), i);
    }
  }
  return outedge;
}

void dfs(const vector<vector<int>> &edge, const int v, vector<bool> &visited,
         vector<int> &order) {
  if (visited[v])
    return;
  visited[v] = true;
  for (const auto &to : edge[v])
    dfs(edge, to, visited, order);
  order.push_back(v);
}

vector<int> topological_sort(const vector<vector<int>> &edge, const int start,
                             const int goal) {
  vector<int> order;
  vector<bool> visited(edge.size(), false);
  dfs(edge, start, visited, order);
  reverse(order.begin(), order.end());
  return order;
}

int main() {
  int S, R;
  cin >> S >> R;

  vector<vector<Edge>> edge(S);
  for (int i = 0; i < R; ++i) {
    int u, v, w;
    cin >> u >> v >> w;
    --u;
    --v;
    edge[u].push_back({u, v, w});
    edge[v].push_back({v, u, w});
  }

  int a, b;
  cin >> a >> b;
  --a;
  --b;

  int Q;
  cin >> Q;
  vector<Query> query;
  for (int i = 0; i < Q; ++i) {
    int c, d;
    cin >> c >> d;
    query.push_back({--c, --d});
  }

  auto cost = Dijkstra(edge, a, b);
  auto optimized_edge = optimize(edge, cost, a, b);
  auto order = topological_sort(optimized_edge, a, b);

  const int BIT = 64;
  for (int i = 0; i < Q; i += BIT) {
    vector<bitset<BIT>> dp(S);
    for (int j = 0; j < BIT && i + j < Q; ++j)
      dp[query[i + j].from].set(j);
    for (const auto &from : order)
      for (const auto &to : optimized_edge[from])
        dp[to] = dp[to] | dp[from];
    for (int j = 0; j < BIT && i + j < Q; ++j)
      cout << (dp[query[i + j].to].test(j) ? "Yes" : "No") << endl;
  }
}