#include <bits/stdc++.h>
using namespace std;
struct basic_of_tree {
  using Tree = vector<vector<int> >;
  void init_depths(Tree& tree, vector<int>& depths, int cur, int parent = -1) {
    for (int nxt : tree[cur])
      if (nxt != parent) {
        depths[nxt] = depths[cur] + 1;
        init_depths(tree, depths, nxt, cur);
      }
  }
  vector<int> get_depths(Tree& tree, vector<int> roots) {
    vector<int> depths(tree.size(), 0);
    for (int root : roots) init_depths(tree, depths, root);
    return depths;
  }
  void init_parents(Tree& tree, vector<int>& parents, int cur,
                    int parent = -1) {
    parents[cur] = parent;
    for (int nxt : tree[cur])
      if (nxt != parent) init_parents(tree, parents, nxt, cur);
  }
  vector<int> get_parents(Tree& tree, vector<int> roots) {
    vector<int> parents(tree.size(), 0);
    for (int root : roots) init_parents(tree, parents, root);
    return parents;
  }
  void init_subtreesz(Tree& tree, vector<int>& subtreesz, int cur,
                      int parent = -1) {
    subtreesz[cur] = 1;
    for (int nxt : tree[cur])
      if (nxt != parent) {
        init_subtreesz(tree, subtreesz, nxt, cur);
        subtreesz[cur] += subtreesz[nxt];
      }
  }
  vector<int> get_subtreesz(Tree& tree, vector<int> roots) {
    vector<int> subtreesz(tree.size(), 0);
    for (int root : roots) init_subtreesz(tree, subtreesz, root);
    return subtreesz;
  }
};
struct LCA_FINDER {
  int size, lg;
  vector<vector<int> > lca;
  vector<int> depths;
  LCA_FINDER(vector<int>& parents, vector<int>& dep) {
    size = parents.size();
    depths = dep;
    lg = log2(size) + 2;
    lca.assign(lg, vector<int>(size));
    for (int e = 0; e < size; e++) lca[0][e] = parents[e];
    build();
  }
  void build() {
    for (int e = 1; e < lg; e++)
      for (int f = 0; f < size; f++)
        if (lca[e - 1][f] != -1) lca[e][f] = lca[e - 1][lca[e - 1][f]];
  }
  int get_lca(int u, int v) {
    if (depths[u] < depths[v]) swap(u, v);
    for (int e = lg - 1; e >= 0; e--)
      if ((depths[u] - depths[v]) & (1 << e)) u = lca[e][u];
    if (u == v) return u;
    for (int e = lg - 1; e >= 0; e--)
      if (lca[e][u] != lca[e][v]) {
        u = lca[e][u];
        v = lca[e][v];
      }
    return lca[0][u];
  }
};
struct HLD {
  static const int default_size = 100100;
  vector<vector<int> > tree;
  vector<int> sz, in, out, nxt, who;
  int size, TIME;
  void __init_vectors() {
    tree.resize(size);
    sz.resize(size);
    in.resize(size);
    out.resize(size);
    nxt.resize(size);
    who.resize(size);
  }
  HLD(int n = default_size) {
    size = n;
    __init_vectors();
    TIME = 0;
  }
  HLD(vector<vector<int> >& T) {
    tree = T;
    size = tree.size();
    __init_vectors();
    TIME = 0;
  }
  void addEdge(int u, int v) {
    tree[u].push_back(v);
    tree[v].push_back(u);
  }
  void init_sz(int root, int parent) {
    sz[root] = 1;
    for (auto& u : tree[root]) {
      if (u == parent) continue;
      init_sz(u, root);
      sz[root] += sz[u];
      if (tree[root][0] == parent || sz[u] > sz[tree[root][0]])
        swap(u, tree[root][0]);
    }
  }
  void init_hld(int root, int parent) {
    if (parent == -1) nxt[root] = root;
    in[root] = TIME++;
    who[in[root]] = root;
    for (auto& u : tree[root]) {
      if (u == parent) continue;
      nxt[u] = (u == tree[root][0] ? nxt[root] : u);
      init_hld(u, root);
    }
    out[root] = TIME;
  }
};
template <typename T>
struct lazy_fenwick {
  vector<T> fenwick[2];
  int size;
  lazy_fenwick(int siz) {
    size = siz + 10;
    fenwick[0].assign(size, T());
    fenwick[1].assign(size, T());
  }
  void updateIn(int bit, int pos, T v) {
    for (; pos < size; pos += pos & -pos) fenwick[bit][pos] += v;
  }
  void update(int l, int r, T v) {
    updateIn(0, l, v);
    updateIn(0, r + 1, -v);
    updateIn(1, l, (l - 1) * v);
    updateIn(1, r + 1, -r * v);
  }
  T queryIn(int bit, int pos) {
    T sum = 0;
    for (; pos; pos -= pos & -pos) sum += fenwick[bit][pos];
    return sum;
  }
  T query(int pos) { return queryIn(0, pos) * pos - queryIn(1, pos); }
  T query(int l, int r) { return query(r) - query(l - 1); }
};
const int maxn = 200100;
int sum[maxn], dp[maxn];
void initialize(vector<vector<int> >& tree, vector<vector<int> >& gap, int cur,
                int p, int d) {
  gap[d].push_back(cur);
  for (int nxt : tree[cur])
    if (nxt != p) initialize(tree, gap, nxt, cur, d + 1);
}
int main() {
  int n, m;
  scanf("%d %d", &n, &m);
  HLD solver(n + 2);
  for (int e = 1; e < n; e++) {
    int x;
    scanf("%d", &x);
    x--;
    solver.addEdge(x, e);
  }
  solver.init_sz(0, -1);
  solver.init_hld(0, -1);
  basic_of_tree cool;
  vector<int> parents = cool.get_parents(solver.tree, {0});
  vector<int> depths = cool.get_depths(solver.tree, {0});
  LCA_FINDER lca(parents, depths);
  vector<vector<tuple<int, int, int> > > operation(n);
  lazy_fenwick<long long> data(n + 10);
  for (int e = 0; e < m; e++) {
    int u, v, w;
    scanf("%d %d %d", &u, &v, &w);
    u--;
    v--;
    operation[lca.get_lca(u, v)].push_back(make_tuple(u, v, w));
  }
  vector<vector<int> > to_solve(n + 10);
  initialize(solver.tree, to_solve, 0, -1, 0);
  reverse(to_solve.begin(), to_solve.end());
  for (auto& it : to_solve) {
    for (int v : it) {
      for (int nxt : solver.tree[v])
        if (nxt != parents[v]) {
          sum[v] += dp[nxt];
        }
      dp[v] = sum[v];
      for (auto& o : operation[v]) {
        int uu, vv, w;
        tie(uu, vv, w) = o;
        int cur = uu;
        int s0 = 0;
        s0 += data.query(solver.in[cur] + 1, solver.in[cur] + 1);
        cur = vv;
        s0 += data.query(solver.in[cur] + 1, solver.in[cur] + 1);
        dp[v] = max(dp[v], s0 + w + sum[v]);
      }
      data.update(solver.in[v] + 1, solver.out[v], sum[v] - dp[v]);
    }
  }
  printf("%d\n", dp[0]);
  return 0;
}
