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

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>
#include <vector>

using namespace std;

const int MAX_N = 10000;
const int MAX_M = 20000;
const int INF = 100000000;

struct edge {
  int to;
  int dis;
  int cost;
  edge() {}
  edge(int t, int d, int c) {
    to = t;
    dis = d;
    cost = c;
  }
};

typedef pair<int, int> P; // first := 最小距&#31163;, second := &#32534;号

//&#36755;入
int N, M;
vector<edge> es[MAX_N + 1]; //&#37051;接矩&#38453;

int d[MAX_N + 1];   // 最小距&#31163;
int pre[MAX_N + 1]; // 前&#32512;&#32467;点
bool
    used[MAX_N +
         1]; // 避免重&#22797;&#32479;&#35745;，&#26631;&#35760;是否已&#35745;算

void dijkstra() {
  // 初始化
  priority_queue<P, vector<P>, greater<P>>
      que; // 返回当前&#31163;1最短距&#31163;
  que.push(P(0, 1));
  fill(d, d + N + 1, INF);
  d[1] = 0;

  while (!que.empty()) {
    P p = que.top();
    que.pop();
    // 若已存在更小距&#31163;，&#21017;忽略
    int v = p.second;
    if (d[v] < p.first)
      continue;
    // 否&#21017;，更新
    for (vector<edge>::iterator it = es[v].begin(); it != es[v].end(); it++) {
      edge e = *it;
      if (d[e.to] > d[v] + e.dis) {
        // 存在更小路径，&#21017;加入&#38431;列
        d[e.to] = d[v] + e.dis;
        pre[e.to] = v;
        que.push(P(d[e.to], e.to));
      } else {
        if (d[e.to] == d[v] + e.dis) {
          // 存在等价路径，&#21017;替&#25442;&#20026;更小的&#36793;
          int tmp, x = pre[e.to];
          for (vector<edge>::iterator it = es[x].begin(); it != es[x].end();
               it++) {
            edge etmp = *it;
            if (etmp.to == e.to) {
              tmp = etmp.cost;
              break;
            }
          }
          if (tmp > e.cost) {
            pre[e.to] = v;
          }
        }
      }
    }
  }
}

void solve() {
  // 求出1到其他点的最短路径
  dijkstra();
  /*	printf("d:\\n");
          for(int i = 1; i <= N; i ++)
                  printf("%d ", d[i]);
          printf("\\n");
          printf("pre:\\n");
          for(int i = 1; i <= N; i ++)
                  printf("%d ", pre[i]);
          printf("\\n\\n");
  */
  fill(used, used + N + 1, false);
  used[1] = true;
  int ans = 0;
  for (int i = 2; i <= N; i++) {
    int k = i;
    while (k != 1 && !used[k]) {
      used[k] = true;
      int x = pre[k], tmp;
      for (vector<edge>::iterator it = es[x].begin(); it != es[x].end(); it++) {
        edge e = *it;
        if (e.to == k) {
          tmp = e.cost;
          break;
        }
      }
      ans += tmp;
      k = x;
    }
  }
  printf("%d\\n", ans);
  for (int i = 1; i <= N; i++)
    es[i].clear();
}

int main(int argc, char const *argv[]) {

  //	freopen("in.txt", "r", stdin);

  while (scanf("%d %d", &N, &M)) {
    if (N == 0 && M == 0)
      break;
    for (int i = 0; i < M; i++) {
      int u, v, x, y;
      scanf("%d %d %d %d", &u, &v, &x, &y);
      es[u].push_back(edge(v, x, y));
      es[v].push_back(edge(u, x, y));
    }
    solve();
  }

  return 0;
}

Error: MLE

Fixed submission:

#include <algorithm>
#include <cstdio>
#include <iostream>
#include <queue>

using namespace std;

const int MAX_N = 10000;
const int MAX_M = 20000;
const int INF = 100000000;

typedef pair<int, int> P; // first := 最小距&#31163;, second := &#32467;点

//&#36755;入
int N, M;
int dis[MAX_N + 1][MAX_N + 1];  // 直接距&#31163;
int cost[MAX_N + 1][MAX_N + 1]; // 代价

int d[MAX_N + 1];   // 最小距&#31163;
int c[MAX_N + 1];   // 累&#31215;代价
int pre[MAX_N + 1]; // 前&#32512;&#32467;点
bool used[MAX_N + 1];

void dijkstra() {
  priority_queue<P, vector<P>, greater<P>> que;
  que.push(P(0, 1));
  fill(d, d + N + 1, INF);
  d[1] = 0;
  //	fill(c, c + N + 1, 0);
  while (!que.empty()) {
    P p = que.top();
    que.pop();
    int v = p.second;
    if (d[v] < p.first)
      continue;
    for (int i = 1; i <= N; i++) {
      if (i == v)
        continue;
      if (d[i] > d[v] + dis[v][i]) {
        d[i] = d[v] + dis[v][i];
        pre[i] = v;
        que.push(P(d[i], i));
        //				c[i] += cost[v][i];
      } else if (d[i] == d[v] + dis[v][i] && cost[pre[i]][i] > cost[v][i]) {
        // 若有等价路径，&#21017;&#36873;取代价小的
        pre[i] = v;
      }
    }
  }
}

void solve() {
  // 求最短距&#31163;
  dijkstra();
  // 挑出最小代价的最短路径
  fill(used, used + N + 1, false);
  used[1] = true;
  int ans = 0;
  for (int i = 2; i <= N; i++) {
    int k = i;
    while (k != 1 && !used[k]) {
      ans += cost[pre[k]][k];
      used[k] = true;
      k = pre[k];
    }
  }
  printf("%d\\n", ans);
}

int main(int argc, char const *argv[]) {

  //	freopen("in.txt", "r", stdin);

  while (scanf("%d %d", &N, &M)) {
    if (N == 0 && M == 0)
      break;
    for (int i = 1; i <= N; i++) {
      fill(dis[i], dis[i] + N + 1, INF);
      fill(cost[i], cost[i] + N + 1, INF);
      dis[i][i] = cost[i][i] = 0;
    }
    for (int i = 0; i < M; i++) {
      int u, v, x, y;
      scanf("%d %d %d %d", &u, &v, &x, &y);
      dis[u][v] = x;
      cost[u][v] = y;
      dis[v][u] = x;
      cost[v][u] = y;
    }
    solve();
  }

  return 0;
}