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

#include <algorithm>
#include <climits>
#include <cstdio>
#include <utility>
#include <vector>

using namespace std;

int n;
int p[801];
int d[801];

int memo[801][801];
int memo_b[801][801];

// to, dist
vector<pair<int, int>> edge[801];

int cost(int e, int f);
int cost_back(int e, int f);

int cost(int e, int f) {
  if (memo[e][f] != -1) {
    return memo[e][f];
  }

  vector<int> b; // cost_back
  vector<int> c; // cost

  for (int i = 0; i < (int)edge[e].size(); i++) {
    int to = edge[e][i].first;
    int dist = edge[e][i].second;

    if (to == f) {
      continue;
    }

    int r = cost_back(to, e);
    if (r == 0) {
      b.push_back(dist);
    } else {
      b.push_back(r + dist * 3);
    }

    c.push_back(cost(to, e) + dist * 2);
  }

  int b_sum = 0;
  for (int i = 0; i < (int)b.size(); i++) {
    b_sum += b[i];
  }

  // printf("b_sum: %d, b.size(): %d\\n", b_sum, b.size());

  int r = b_sum;
  if (b.size() == 0) {
    r = 0;
  }
  for (int i = 0; i < (int)b.size(); i++) {
    r = min(r, b_sum - b[i] + c[i]);
  }

  memo[e][f] = r;
  return r;
}

int cost_back(int e, int f) {
  if (memo_b[e][f] != -1) {
    return memo_b[e][f];
  }

  int s = 0;

  for (int i = 0; i < (int)edge[e].size(); i++) {
    int to = edge[e][i].first;
    int dist = edge[e][i].second;

    if (to == f) {
      continue;
    }

    int r = cost_back(to, e);
    if (r == 0) { // 'to' is a leaf
      s += dist;
    } else {
      s += r + dist * 3;
    }
  }

  memo_b[e][f] = s;
  return s;
}

int solve() {
  int ans = INT_MAX;
  for (int i = 1; i <= n; i++) {
    ans = min(ans, cost(i, -1));
  }
  return ans;
}

int main() {
  for (;;) {
    scanf("%d", &n);

    if (!n) {
      break;
    }

    for (int i = 2; i <= n; i++) {
      scanf("%d", &p[i]);
    }
    for (int i = 2; i <= n; i++) {
      scanf("%d", &d[i]);
    }

    for (int i = 0; i < 801; i++) {
      edge[i].clear();
      for (int j = 0; j < 801; j++) {
        memo[i][j] = -1;
        memo_b[i][j] = -1;
      }
    }

    for (int i = 2; i <= n; i++) {
      int f = i;
      int t = p[i];
      int c = d[i];
      edge[f].push_back(make_pair(t, c));
      edge[t].push_back(make_pair(f, c));
    }

#if 0
        for (int i = 1; i <= n; i++) {
            printf("%d:", i);
            for (unsigned j = 0; j < edge[i].size(); j++) {
                printf(" (%d,%d)", edge[i][j].first, edge[i][j].second);
            }
            printf("\\n");
        }
#endif

    printf("%d\\n", solve());
  }
  return 0;
}

Error: TLE

Fixed submission:

#include <algorithm>
#include <climits>
#include <cstdio>
#include <utility>
#include <vector>

using namespace std;

int n;
int p[801];
int d[801];

// to, dist
vector<pair<int, int>> edge[801];

int cost(int e, int f);
int cost_back(int e, int f);

int cost(int e, int f) {
  vector<int> b; // cost_back
  vector<int> c; // cost

  for (int i = 0; i < (int)edge[e].size(); i++) {
    int to = edge[e][i].first;
    int dist = edge[e][i].second;

    if (to == f) {
      continue;
    }

    int r = cost_back(to, e);
    if (r == 0) {
      b.push_back(dist);
    } else {
      b.push_back(r + dist * 3);
    }

    c.push_back(cost(to, e) + dist * 2);
  }

  int b_sum = 0;
  for (int i = 0; i < (int)b.size(); i++) {
    b_sum += b[i];
  }

  // printf("b_sum: %d, b.size(): %d\\n", b_sum, b.size());

  int r = b_sum;
  if (b.size() == 0) {
    r = 0;
  }
  for (int i = 0; i < (int)b.size(); i++) {
    r = min(r, b_sum - b[i] + c[i]);
  }

  return r;
}

int cost_back(int e, int f) {
  int s = 0;

  for (int i = 0; i < (int)edge[e].size(); i++) {
    int to = edge[e][i].first;
    int dist = edge[e][i].second;

    if (to == f) {
      continue;
    }

    int r = cost_back(to, e);
    if (r == 0) { // 'to' is a leaf
      s += dist;
    } else {
      s += r + dist * 3;
    }
  }

  return s;
}

int solve() {
  int ans = INT_MAX;
  for (int i = 1; i <= n; i++) {
    ans = min(ans, cost(i, -1));
  }
  return ans;
}

int main() {
  for (;;) {
    scanf("%d", &n);

    if (!n) {
      break;
    }

    for (int i = 2; i <= n; i++) {
      scanf("%d", &p[i]);
    }
    for (int i = 2; i <= n; i++) {
      scanf("%d", &d[i]);
    }

    for (int i = 0; i < 801; i++) {
      edge[i].clear();
    }

    for (int i = 2; i <= n; i++) {
      int f = i;
      int t = p[i];
      int c = d[i];
      edge[f].push_back(make_pair(t, c));
      edge[t].push_back(make_pair(f, c));
    }

#if 0
        for (int i = 1; i <= n; i++) {
            printf("%d:", i);
            for (unsigned j = 0; j < edge[i].size(); j++) {
                printf(" (%d,%d)", edge[i][j].first, edge[i][j].second);
            }
            printf("\\n");
        }
#endif

    printf("%d\\n", solve());
  }
  return 0;
}