import std.stdio;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;

struct Edge {
    int from, to, cost;
}

class UnionFind {
    int[] parent;
    int[] group_size;
    this(int N) {
        parent = new int[N];
        parent[] = -1;
        group_size = new int[N];
        group_size[] = 1;
    }
    int root(int x) {
        if (parent[x] == -1) return x;
        return parent[x] = root(parent[x]);
    }
    void merge(int x, int y) {
        x = root(x);
        y = root(y);
        if (x == y) return;
        parent[y] = x;
        group_size[x] += group_size[y];
    }
    bool query(int x, int y) {
        return root(x) == root(y);
    }
    int size(int x) {
        x = root(x);
        return group_size[x];
    }
}

void main() {
    int N; scanf("%d\n", &N);
    Edge[] es;
    foreach (i; 0 .. N - 1) {
        int a, b, c; scanf("%d %d %d\n", &a, &b, &c);
        es ~= Edge(a, b, c);
    }
    es.sort!"a.cost < b.cost";
    //writeln(es);
    auto uf = new UnionFind(N);
    long Ans = 0;
    foreach (e; es) {
        if (uf.query(e.from, e.to)) assert(0);
        Ans += cast(long)(e.cost) * uf.size(e.from) * uf.size(e.to);
        uf.merge(e.from, e.to);
    }
    writeln(Ans);
}