Problem p02579 (C++) — buggy submission, verdict: Time Limit Exceeded

#include <algorithm>
#include <climits>
#include <cmath>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;
typedef long long ll;

struct Edge;
struct Node {
  ll cost;
  bool isClosed;
  vector<Edge *> edges;
  Node *last;

  Node() {}
};

struct NODE {
  Node *node;
  ll costWhenPushed;
  bool operator<(const NODE &rhs) const {
    return costWhenPushed > rhs.costWhenPushed;
  } // 逆にする
  NODE(Node *n, ll cost) {
    node = n;
    costWhenPushed = cost;
  }
};

struct Edge {
  Node *node0;
  Node *node1;
  ll cost;
};

vector<Node> Nodes;
vector<Edge> Edges;

ll Dijkstra_Find(Node *s, Node *g) {
  // 初期化
  for (int i = 0; i < Nodes.size(); i++) {
    Nodes[i].cost = &Nodes[i] == s ? 0 : LLONG_MAX / 2;
    Nodes[i].isClosed = false;
    Nodes[i].last = nullptr;
  }
  priority_queue<NODE> que;
  que.push(NODE(s, 0));

  while (!que.empty()) {
    Node *n = que.top().node;
    ll costWhenPushed = que.top().costWhenPushed;
    que.pop();
    if (n->cost < costWhenPushed) {
      continue;
    }
    n->isClosed = true;

    int size = (n->edges).size();
    for (int i = 0; i < size; i++) {
      Node *processNode = (n->edges)[i]->node0 == n ? (n->edges)[i]->node1
                                                    : (n->edges)[i]->node0;
      if (processNode->isClosed) {
        continue;
      }

      ll newCost = n->cost + (n->edges)[i]->cost;
      if (newCost < processNode->cost) {
        processNode->cost = newCost;
        processNode->last = n;
        que.push(NODE(processNode, newCost));
      }
    }
  }

  return g->cost;
}

int main() {
  int wall = 99999999;
  int H, W;
  int Ch, Cw, Dh, Dw;
  cin >> H >> W >> Ch >> Cw >> Dh >> Dw;
  static int Mass[1002][1002];
  for (int i = 0; i < 1002; i++) {
    for (int j = 0; j < 1002; j++) {
      Mass[i][j] = wall;
    }
  }
  int count = 0;
  for (int h = 1; h <= H; h++) {
    string line;
    cin >> line;
    for (int w = 1; w <= W; w++) {
      if (line[w - 1] == '.') {
        count++;
        Mass[h][w] = count;
      }
    }
  }

  for (int step = 0; step < 50; step++) {
    for (int h = 1; h <= H; h++) {
      for (int w = 1; w <= W; w++) {
        if (Mass[h][w] != wall) {
          Mass[h][w] = min(Mass[h][w], Mass[h - 1][w]);
          Mass[h][w] = min(Mass[h][w], Mass[h][w - 1]);
          Mass[h][w] = min(Mass[h][w], Mass[h + 1][w]);
          Mass[h][w] = min(Mass[h][w], Mass[h][w + 1]);
        }
      }
    }
  }

  static int Mass2[1010][1010];
  for (int i = 0; i < 1010; i++) {
    for (int j = 0; j < 1010; j++) {
      Mass2[i][j] = wall;
    }
  }
  set<int> counter;
  map<int, int> cor;
  for (int h = 1; h <= H; h++) {
    for (int w = 1; w <= W; w++) {
      if (Mass[h][w] != wall) {
        if (counter.find(Mass[h][w]) == counter.end()) {
          counter.insert(Mass[h][w]);
          cor[Mass[h][w]] = counter.size();
        }
        Mass2[h][w] = cor[Mass[h][w]];
      } else {
        Mass2[h][w] = wall;
      }
    }
  }

  /*
  for(int h = 1; h <= H; h++){
          for(int w = 1; w <= W; w++){
                  cout << Mass2[h][w] << " ";
          }
          cout << endl;
  }
  */

  for (int i = 0; i < counter.size() + 2; i++) {
    Node node;
    Nodes.push_back(node);
  }
  for (int i = 0; i < 1000 * 1000; i++) {
    Edge edge;
    Edges.push_back(edge);
  }

  int edgeCount = 0;
  set<pair<int, int>> check;
  for (int h = 1; h <= H; h++) {
    for (int w = 1; w <= W; w++) {
      if (Mass2[h][w] == wall) {
        continue;
      }
      Node *node1 = &Nodes[Mass2[h][w]];
      for (int x = -2; x <= 2; x++) {
        for (int y = -2; y <= 2; y++) {
          if (x != 0 || y != 0) {
            if (h + x >= 0 && h + x <= H && w + y >= 0 && w + y <= W) {
              // cout << h << " " << w << " "<< h+x << " " << w+y << endl;
              // cout << Mass2[h][w] << endl;
              if (Mass2[h + x][w + y] == wall) {
                // pass
              } else if (Mass2[h][w] != Mass2[h + x][w + y]) {
                if (check.find(
                        make_pair(min(Mass2[h][w], Mass2[h + x][w + y]),
                                  max(Mass2[h][w], Mass2[h + x][w + y]))) !=
                    check.end()) {
                  continue;
                }
                Node *node2 = &Nodes[Mass2[h + x][w + y]];
                Edge *edge12 = &Edges[edgeCount];
                edge12->node0 = node1;
                edge12->node1 = node2;
                edge12->cost = 1;
                node1->edges.push_back(edge12);
                node2->edges.push_back(edge12);
                edgeCount++;
                check.insert(make_pair(min(Mass2[h][w], Mass2[h + x][w + y]),
                                       max(Mass2[h][w], Mass2[h + x][w + y])));
              }
            }
          }
        }
      }
    }
  }

  ll ans = Dijkstra_Find(&Nodes[Mass2[Ch][Cw]], &Nodes[Mass2[Dh][Dw]]);
  if (ans > 100010001000) {
    ans = -1;
  }
  cout << ans << endl;

  return 0;
}


Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cmath>
#include <functional>
#include <iostream>
#include <list>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <unordered_set>
#include <vector>

using namespace std;
typedef long long ll;

struct Edge;
struct Node {
  ll cost;
  bool isClosed;
  vector<Edge *> edges;
  Node *last;

  Node() {}
};

struct NODE {
  Node *node;
  ll costWhenPushed;
  bool operator<(const NODE &rhs) const {
    return costWhenPushed > rhs.costWhenPushed;
  } // 逆にする
  NODE(Node *n, ll cost) {
    node = n;
    costWhenPushed = cost;
  }
};

struct Edge {
  Node *node0;
  Node *node1;
  ll cost;
};

vector<Node> Nodes;
vector<Edge> Edges;

ll Dijkstra_Find(Node *s, Node *g) {
  // 初期化
  for (int i = 0; i < Nodes.size(); i++) {
    Nodes[i].cost = &Nodes[i] == s ? 0 : LLONG_MAX / 2;
    Nodes[i].isClosed = false;
    Nodes[i].last = nullptr;
  }
  priority_queue<NODE> que;
  que.push(NODE(s, 0));

  while (!que.empty()) {
    Node *n = que.top().node;
    ll costWhenPushed = que.top().costWhenPushed;
    que.pop();
    if (n->cost < costWhenPushed) {
      continue;
    }
    n->isClosed = true;

    int size = (n->edges).size();
    for (int i = 0; i < size; i++) {
      Node *processNode = (n->edges)[i]->node0 == n ? (n->edges)[i]->node1
                                                    : (n->edges)[i]->node0;
      if (processNode->isClosed) {
        continue;
      }

      ll newCost = n->cost + (n->edges)[i]->cost;
      if (newCost < processNode->cost) {
        processNode->cost = newCost;
        processNode->last = n;
        que.push(NODE(processNode, newCost));
      }
    }
  }

  return g->cost;
}

int main() {
  int wall = 99999999;
  int H, W;
  int Ch, Cw, Dh, Dw;
  cin >> H >> W >> Ch >> Cw >> Dh >> Dw;
  static int Mass[1002][1002];
  for (int i = 0; i < 1002; i++) {
    for (int j = 0; j < 1002; j++) {
      Mass[i][j] = wall;
    }
  }
  int count = 0;
  for (int h = 1; h <= H; h++) {
    string line;
    cin >> line;
    for (int w = 1; w <= W; w++) {
      if (line[w - 1] == '.') {
        count++;
        Mass[h][w] = count;
      }
    }
  }

  for (int step = 0; step < 500; step++) {
    for (int h = 1; h <= H; h++) {
      for (int w = 1; w <= W; w++) {
        if (Mass[h][w] != wall) {
          Mass[h][w] = min(Mass[h][w], Mass[h - 1][w]);
          Mass[h][w] = min(Mass[h][w], Mass[h][w - 1]);
          Mass[h][w] = min(Mass[h][w], Mass[h + 1][w]);
          Mass[h][w] = min(Mass[h][w], Mass[h][w + 1]);
        }
      }
    }
  }

  static int Mass2[1010][1010];
  for (int i = 0; i < 1010; i++) {
    for (int j = 0; j < 1010; j++) {
      Mass2[i][j] = wall;
    }
  }
  set<int> counter;
  map<int, int> cor;
  for (int h = 1; h <= H; h++) {
    for (int w = 1; w <= W; w++) {
      if (Mass[h][w] != wall) {
        if (counter.find(Mass[h][w]) == counter.end()) {
          counter.insert(Mass[h][w]);
          cor[Mass[h][w]] = counter.size();
        }
        Mass2[h][w] = cor[Mass[h][w]];
      } else {
        Mass2[h][w] = wall;
      }
    }
  }

  /*
  for(int h = 1; h <= H; h++){
          for(int w = 1; w <= W; w++){
                  cout << Mass2[h][w] << " ";
          }
          cout << endl;
  }
  */

  for (int i = 0; i < counter.size() + 2; i++) {
    Node node;
    Nodes.push_back(node);
  }
  for (int i = 0; i < 1000 * 1000; i++) {
    Edge edge;
    Edges.push_back(edge);
  }

  int edgeCount = 0;
  set<pair<int, int>> check;
  for (int h = 1; h <= H; h++) {
    for (int w = 1; w <= W; w++) {
      if (Mass2[h][w] == wall) {
        continue;
      }
      Node *node1 = &Nodes[Mass2[h][w]];
      for (int x = -2; x <= 2; x++) {
        for (int y = -2; y <= 2; y++) {
          if (x != 0 || y != 0) {
            if (h + x >= 0 && h + x <= H && w + y >= 0 && w + y <= W) {
              // cout << h << " " << w << " "<< h+x << " " << w+y << endl;
              // cout << Mass2[h][w] << endl;
              if (Mass2[h + x][w + y] == wall) {
                // pass
              } else if (Mass2[h][w] != Mass2[h + x][w + y]) {
                if (check.find(
                        make_pair(min(Mass2[h][w], Mass2[h + x][w + y]),
                                  max(Mass2[h][w], Mass2[h + x][w + y]))) !=
                    check.end()) {
                  continue;
                }
                Node *node2 = &Nodes[Mass2[h + x][w + y]];
                Edge *edge12 = &Edges[edgeCount];
                edge12->node0 = node1;
                edge12->node1 = node2;
                edge12->cost = 1;
                node1->edges.push_back(edge12);
                node2->edges.push_back(edge12);
                edgeCount++;
                check.insert(make_pair(min(Mass2[h][w], Mass2[h + x][w + y]),
                                       max(Mass2[h][w], Mass2[h + x][w + y])));
              }
            }
          }
        }
      }
    }
  }

  ll ans = Dijkstra_Find(&Nodes[Mass2[Ch][Cw]], &Nodes[Mass2[Dh][Dw]]);
  if (ans > 100010001000) {
    ans = -1;
  }
  cout << ans << endl;

  return 0;
}