#include <bits/stdc++.h>
using namespace std;
template <class T>
T sqr(const T &a) {
  return a * a;
}
const int MAXN = 4e5 + 100, LOG = 20;
vector<int> a[MAXN];
int tin[MAXN], tout[MAXN], timer, up[MAXN][LOG];
int w[MAXN], path[MAXN], nextV[MAXN], posV[MAXN], p[MAXN];
vector<int> pathVerts[MAXN];
vector<long long> tree[MAXN];
long long d[MAXN];
vector<pair<pair<int, int>, int> > queries[MAXN];
inline int upper(int x, int y) {
  return tin[x] <= tin[y] && tout[x] >= tout[y];
}
inline int jump(int x, int y) {
  for (int i = (LOG)-1; i >= 0; i--) {
    if (!upper(up[x][i], y)) x = up[x][i];
  }
  return x;
}
inline int lca(int x, int y) {
  if (upper(x, y)) return x;
  if (upper(y, x)) return y;
  return p[jump(x, y)];
}
int dfsSum(int v) {
  w[v] = 1;
  tin[v] = timer++;
  for (int to : a[v]) {
    w[v] += dfsSum(to);
  }
  tout[v] = timer++;
  return w[v];
}
void dfsHLD(int v, int root) {
  path[v] = root;
  pathVerts[root].push_back(v);
  if (v != root) {
    nextV[p[v]] = v;
    posV[v] = posV[p[v]] + 1;
  } else {
    posV[v] = 0;
  }
  nextV[v] = -1;
  for (int to : a[v]) {
    if (2 * w[to] > w[v])
      dfsHLD(to, root);
    else
      dfsHLD(to, to);
  }
}
void update(int vl, int vr, int pos, long long val, int v, int tNum) {
  if (vl + 1 == vr) {
    tree[tNum][v] = val;
    return;
  }
  int vm = (vl + vr) / 2;
  if (vm > pos)
    update(vl, vm, pos, val, 2 * v, tNum);
  else
    update(vm, vr, pos, val, 2 * v + 1, tNum);
  tree[tNum][v] = tree[tNum][2 * v] + tree[tNum][2 * v + 1];
}
long long get(int vl, int vr, int l, int r, int v, int tNum) {
  if (vl >= l && vr <= r) return tree[tNum][v];
  if (vl >= r || vr <= l) return 0;
  int vm = (vl + vr) / 2;
  return get(vl, vm, l, r, 2 * v, tNum) + get(vm, vr, l, r, 2 * v + 1, tNum);
}
long long get(int vUp, int vDown) {
  long long res = 0;
  int prevV = -1;
  while (!upper(vDown, vUp)) {
    if (path[vUp] != path[vDown]) {
      res += get(0, (int)pathVerts[path[vDown]].size(), 0, posV[vDown] + 1, 1,
                 path[vDown]);
    } else {
      res += get(0, (int)pathVerts[path[vDown]].size(), posV[vUp] + 1,
                 posV[vDown] + 1, 1, path[vDown]);
    }
    if (prevV != -1 && nextV[vDown] != -1) {
      res = res + d[nextV[vDown]] - d[prevV];
    } else if (prevV != -1) {
      res -= d[prevV];
    } else if (prevV == -1 && nextV[vDown] != -1) {
      res = res + d[nextV[vDown]];
    }
    prevV = path[vDown];
    vDown = p[path[vDown]];
  }
  return res;
}
void dfsAns(int v) {
  long long sum = 0;
  for (int to : a[v]) {
    dfsAns(to);
    d[v] += d[to];
  }
  sum = d[v];
  for (auto q : queries[v]) {
    long long z = q.second + sum;
    if (q.first.first != v)
      z = z - d[jump(q.first.first, v)] + get(v, q.first.first);
    if (q.first.second != v)
      z = z - d[jump(q.first.second, v)] + get(v, q.first.second);
    d[v] = max(d[v], z);
  }
  if (nextV[v] != -1) sum -= d[nextV[v]];
  update(0, (int)pathVerts[path[v]].size(), posV[v], sum, 1, path[v]);
}
int main() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  int n, m;
  scanf("%d%d", &n, &m);
  for (int i = (1); i < (n); i++) {
    scanf("%d", &p[i]);
    p[i]--;
    a[p[i]].push_back(i);
  }
  dfsSum(0);
  dfsHLD(0, 0);
  for (int i = 0; i < (n); i++) tree[i].resize(4 * pathVerts[i].size() + 3);
  for (int i = 0; i < (n); i++) {
  }
  for (int i = 0; i < (n); i++) up[i][0] = p[i];
  for (int i = (1); i < (LOG); i++)
    for (int v = 0; v < (n); v++) up[v][i] = up[up[v][i - 1]][i - 1];
  for (int i = 0; i < (m); i++) {
    int u, v, c;
    scanf("%d%d%d", &u, &v, &c);
    u--, v--;
    int z = lca(u, v);
    queries[z].push_back(make_pair(make_pair(u, v), c));
  }
  dfsAns(0);
  cerr << 123 << endl;
  cout << d[0] << endl;
}
