#include <bits/stdc++.h>
using namespace std;
const string YES = "YES";
const string NO = "NO";
vector<int> smallest_factor;
vector<bool> prime;
vector<int> primes;
const int P_MAX = int(1e5) + 5;
void sieve(int maximum) {
  maximum = max(maximum, 1);
  smallest_factor.assign(maximum + 1, 0);
  prime.assign(maximum + 1, true);
  prime[0] = prime[1] = false;
  primes = {};
  for (int p = 2; p <= maximum; p++)
    if (prime[p]) {
      smallest_factor[p] = p;
      primes.push_back(p);
      for (int64_t i = int64_t(p) * p; i <= maximum; i += p)
        if (prime[i]) {
          prime[i] = false;
          smallest_factor[i] = p;
        }
    }
}
long long int gcd(long long int a, long long int b) {
  while (true) {
    if (a == 0) return b;
    b %= a;
    if (b == 0) return a;
    a %= b;
  }
}
long long int lcm(long long int a, long long int b) {
  long long int temp = gcd(a, b);
  return temp ? (a / temp * b) : 0;
}
template <typename I, typename P>
I binarysearch(const P& predicate, I l, I r) {
  l--;
  while (r - l > 1) {
    auto mid = l + (r - l) / 2;
    if (predicate(mid))
      r = mid;
    else
      l = mid;
  }
  return r;
}
struct Edge {
  int from, to, weight, index;
  bool del;
  Edge(int f, int t, int w, int idx) {
    from = f;
    to = t;
    weight = w;
    index = idx;
    del = false;
  }
  bool operator<(const Edge& e) const { return weight > e.weight; }
  bool operator==(const Edge& e) const {
    return (from == e.from && to == e.to && weight == e.weight);
  }
};
struct DisjointSet {
  vector<int> ranks;
  vector<int> parent;
  DisjointSet(int n) {
    ranks.resize(n, 0);
    parent.resize(n);
    for (int i = 0; i < n; i++) parent[i] = i;
  }
  int findSet(int v) {
    return parent[v] = ((parent[v] == v) ? v : findSet(parent[v]));
  }
  bool unionSet(int u, int v) {
    int x = findSet(u);
    int y = findSet(v);
    if (x == y) return false;
    if (ranks[x] == ranks[y]) ranks[x]++;
    if (ranks[x] > ranks[y]) {
      parent[y] = x;
    } else
      parent[x] = y;
    return true;
  }
};
pair<int, vector<Edge> > getMST(int n, vector<Edge> edges) {
  int cost = 0;
  priority_queue<Edge> q;
  vector<Edge> res;
  DisjointSet djSet(n);
  for (int i = 0; i < edges.size(); i++) {
    if (!edges[i].del) q.push(edges[i]);
  }
  while (!q.empty()) {
    Edge curE = q.top();
    q.pop();
    if (djSet.unionSet(curE.from, curE.to)) {
      cost += curE.weight;
      res.push_back(curE);
    }
  }
  if (res.size() != n - 1) return make_pair(1e9, vector<Edge>());
  return make_pair(cost, res);
}
template <class A, class B>
auto findMin(A a, B b) -> decltype(a < b ? a : b) {
  return (a < b) ? a : b;
}
void file_i_o() {
  ios_base::sync_with_stdio(0);
  cin.tie(0);
  cout.tie(0);
}
const int modd = 1000000009;
const int MAX = 1000007;
int n, m, k, p, q;
int a, b, c;
int f[102][102];
vector<int> arr;
void run_case() {
  cin >> n >> m;
  memset(f, 0, sizeof f);
  arr.resize(n + 1, 0);
  for (int i = (0); i < m; i++) {
    cin >> a >> b >> c;
    arr[a] += c;
    arr[b] -= c;
  }
  long long int sum = 0;
  for (int i = (1); i < n + 1; i++) {
    if (arr[i] > 0) sum += arr[i];
  }
  cout << sum << '\n';
}
int main() {
  clock_t begin = clock();
  file_i_o();
  int tests = 1;
  while (tests-- > 0) run_case();
  return 0;
}
