import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.*;

public class CF1156D {
    public static void main(String[] args) throws Exception {
        boolean local = System.getProperty("ONLINE_JUDGE") == null;
        boolean async = false;

        Charset charset = Charset.forName("ascii");

        FastIO io = local ? new FastIO(new FileInputStream("D:\\DATABASE\\TESTCASE\\Code.in"), System.out, charset) : new FastIO(System.in, System.out, charset);
        Task task = new Task(io, new Debug(local));

        if (async) {
            Thread t = new Thread(null, task, "dalt", 1 << 27);
            t.setPriority(Thread.MAX_PRIORITY);
            t.start();
            t.join();
        } else {
            task.run();
        }

        if (local) {
            io.cache.append("\n\n--memory -- \n" + ((Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) >> 20) + "M");
        }

        io.flush();
    }

    public static class Task implements Runnable {
        final FastIO io;
        final Debug debug;
        int inf = (int) 1e8;
        int mod = (int) 1e9 + 7;

        public int mod(int val) {
            val %= mod;
            if (val < 0) {
                val += mod;
            }
            return val;
        }

        public int mod(long val) {
            val %= mod;
            if (val < 0) {
                val += mod;
            }
            return (int) val;
        }

        public Task(FastIO io, Debug debug) {
            this.io = io;
            this.debug = debug;
        }

        @Override
        public void run() {
            solve();
        }

        public void solve() {
            int n = io.readInt();
            Node[] nodes = new Node[n + 1];
            for (int i = 1; i <= n; i++) {
                nodes[i] = new Node();
                nodes[i].id = i;
            }

            for (int i = 1; i < n; i++) {
                Edge edge = new Edge();
                edge.a = nodes[io.readInt()];
                edge.b = nodes[io.readInt()];
                edge.c = io.readInt();
                edge.a.edges.add(edge);
                edge.b.edges.add(edge);
            }

            dfs(nodes[1], null);
            long sum = 0;
            for (int i = 1; i <= n; i++) {
                sum += nodes[i].cnt;
            }
            io.cache.append(sum);
        }

        static void dfs(Node root, Edge from) {

            for (Edge edge : root.edges) {
                if (edge == from) {
                    continue;
                }
                Node node = edge.another(root);
                dfs(node, edge);

                long[] tmpDp = new long[4];
                if (edge.c == 0) {
                    tmpDp[2] = node.dp[2] + node.dp[3];
                    tmpDp[0] = node.dp[0] + 1;
                } else {
                    tmpDp[3] = node.dp[3] + 1;
                    tmpDp[1] = node.dp[0] + node.dp[1];
                }

                root.cnt += (root.dp[2] + root.dp[3] + root.dp[0]) * tmpDp[0]; // -> 00
                root.cnt += (tmpDp[2] + tmpDp[3] + tmpDp[0]) * root.dp[0];
                root.cnt += (root.dp[3]) * tmpDp[1];// -> 10
                root.cnt += (tmpDp[3]) * root.dp[1];
                root.cnt += (root.dp[3]) * tmpDp[3];// -> 11
                root.cnt += (tmpDp[3]) * root.dp[3];// -> 11

                for (int i = 0; i < 4; i++) {
                    root.dp[i] += tmpDp[i];
                }
            }

            root.cnt += root.dp[0] * 2 + root.dp[1] + root.dp[2] + root.dp[3] * 2;
        }
    }

    public static class Node {
        List<Edge> edges = new ArrayList<>();
        long[] dp = new long[4];
        long cnt;
        int id;
    }

    public static class Edge {
        Node a;
        Node b;
        int c;

        Node another(Node me) {
            return a == me ? b : a;
        }
    }

    public static class Randomized {
        static Random random = new Random(123456789);

        public static double nextDouble(double min, double max) {
            return random.nextDouble() * (max - min) + min;
        }

        public static void randomizedArray(int[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                int tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void randomizedArray(long[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                long tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void randomizedArray(double[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                double tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static void randomizedArray(float[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                float tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static <T> void randomizedArray(T[] data, int from, int to) {
            to--;
            for (int i = from; i <= to; i++) {
                int s = nextInt(i, to);
                T tmp = data[i];
                data[i] = data[s];
                data[s] = tmp;
            }
        }

        public static int nextInt(int l, int r) {
            return random.nextInt(r - l + 1) + l;
        }
    }

    public static class Mathematics {

        public static int ceilPowerOf2(int x) {
            return 32 - Integer.numberOfLeadingZeros(x - 1);
        }

        public static int floorPowerOf2(int x) {
            return 31 - Integer.numberOfLeadingZeros(x);
        }

        public static long modmul(long a, long b, long mod) {
            return b == 0 ? 0 : ((modmul(a, b >> 1, mod) << 1) % mod + a * (b & 1)) % mod;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static int gcd(int a, int b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static int gcd0(int a, int b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static int extgcd(int a, int b, int[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                int g = extgcd0(b, a, coe);
                int tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static int extgcd0(int a, int b, int[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            int g = extgcd0(b, a % b, coe);
            int n = coe[0];
            int m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get the greatest common divisor of a and b
         */
        public static long gcd(long a, long b) {
            return a >= b ? gcd0(a, b) : gcd0(b, a);
        }

        private static long gcd0(long a, long b) {
            return b == 0 ? a : gcd0(b, a % b);
        }

        public static long extgcd(long a, long b, long[] coe) {
            if (a >= b) {
                return extgcd0(a, b, coe);
            } else {
                long g = extgcd0(b, a, coe);
                long tmp = coe[0];
                coe[0] = coe[1];
                coe[1] = tmp;
                return g;
            }
        }

        private static long extgcd0(long a, long b, long[] coe) {
            if (b == 0) {
                coe[0] = 1;
                coe[1] = 0;
                return a;
            }
            long g = extgcd0(b, a % b, coe);
            long n = coe[0];
            long m = coe[1];
            coe[0] = m;
            coe[1] = n - m * (a / b);
            return g;
        }

        /**
         * Get y where x * y = 1 (% mod)
         */
        public static int inverse(int x, int mod) {
            return pow(x, mod - 2, mod);
        }

        /**
         * Get x^n(% mod)
         */
        public static int pow(int x, int n, int mod) {
            int bit = 31 - Integer.numberOfLeadingZeros(n);
            long product = 1;
            for (; bit >= 0; bit--) {
                product = product * product % mod;
                if (((1 << bit) & n) != 0) {
                    product = product * x % mod;
                }
            }
            return (int) product;
        }

        public static long longpow(long x, long n, long mod) {
            if (n == 0) {
                return 1;
            }
            long prod = longpow(x, n >> 1, mod);
            prod = modmul(prod, prod, mod);
            if ((n & 1) == 1) {
                prod = modmul(prod, x, mod);
            }
            return prod;
        }

        /**
         * Get x % mod
         */
        public static int mod(int x, int mod) {
            x %= mod;
            if (x < 0) {
                x += mod;
            }
            return x;
        }

        public static int mod(long x, int mod) {
            x %= mod;
            if (x < 0) {
                x += mod;
            }
            return (int) x;
        }

        /**
         * Get n!/(n-m)!
         */
        public static long permute(int n, int m) {
            return m == 0 ? 1 : n * permute(n - 1, m - 1);
        }

        /**
         * Put all primes less or equal to limit into primes after offset
         */
        public static int eulerSieve(int limit, int[] primes, int offset) {
            boolean[] isComp = new boolean[limit + 1];
            int wpos = offset;
            for (int i = 2; i <= limit; i++) {
                if (!isComp[i]) {
                    primes[wpos++] = i;
                }
                for (int j = offset, until = limit / i; j < wpos && primes[j] <= until; j++) {
                    int pi = primes[j] * i;
                    isComp[pi] = true;
                    if (i % primes[j] == 0) {
                        break;
                    }
                }
            }
            return wpos - offset;
        }

        /**
         * Round x into integer
         */
        public static int intRound(double x) {
            if (x < 0) {
                return -(int) (-x + 0.5);
            }
            return (int) (x + 0.5);
        }

        /**
         * Round x into long
         */
        public static long longRound(double x) {
            if (x < 0) {
                return -(long) (-x + 0.5);
            }
            return (long) (x + 0.5);
        }
    }

    public static class FastIO {
        public final StringBuilder cache = new StringBuilder();
        private final InputStream is;
        private final OutputStream os;
        private final Charset charset;
        private StringBuilder defaultStringBuf = new StringBuilder(1 << 8);
        private byte[] buf = new byte[1 << 13];
        private int bufLen;
        private int bufOffset;
        private int next;

        public FastIO(InputStream is, OutputStream os, Charset charset) {
            this.is = is;
            this.os = os;
            this.charset = charset;
        }

        public FastIO(InputStream is, OutputStream os) {
            this(is, os, Charset.forName("ascii"));
        }

        private int read() {
            while (bufLen == bufOffset) {
                bufOffset = 0;
                try {
                    bufLen = is.read(buf);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
                if (bufLen == -1) {
                    return -1;
                }
            }
            return buf[bufOffset++];
        }

        public void skipBlank() {
            while (next >= 0 && next <= 32) {
                next = read();
            }
        }

        public int readInt() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            int val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public long readLong() {
            int sign = 1;

            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+' ? 1 : -1;
                next = read();
            }

            long val = 0;
            if (sign == 1) {
                while (next >= '0' && next <= '9') {
                    val = val * 10 + next - '0';
                    next = read();
                }
            } else {
                while (next >= '0' && next <= '9') {
                    val = val * 10 - next + '0';
                    next = read();
                }
            }

            return val;
        }

        public double readDouble() {
            boolean sign = true;
            skipBlank();
            if (next == '+' || next == '-') {
                sign = next == '+';
                next = read();
            }

            long val = 0;
            while (next >= '0' && next <= '9') {
                val = val * 10 + next - '0';
                next = read();
            }
            if (next != '.') {
                return sign ? val : -val;
            }
            next = read();
            long radix = 1;
            long point = 0;
            while (next >= '0' && next <= '9') {
                point = point * 10 + next - '0';
                radix = radix * 10;
                next = read();
            }
            double result = val + (double) point / radix;
            return sign ? result : -result;
        }

        public String readString(StringBuilder builder) {
            skipBlank();

            while (next > 32) {
                builder.append((char) next);
                next = read();
            }

            return builder.toString();
        }

        public String readString() {
            defaultStringBuf.setLength(0);
            return readString(defaultStringBuf);
        }

        public int readLine(char[] data, int offset) {
            int originalOffset = offset;
            while (next != -1 && next != '\n') {
                data[offset++] = (char) next;
                next = read();
            }
            return offset - originalOffset;
        }

        public int readString(char[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (char) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public int readString(byte[] data, int offset) {
            skipBlank();

            int originalOffset = offset;
            while (next > 32) {
                data[offset++] = (byte) next;
                next = read();
            }

            return offset - originalOffset;
        }

        public char readChar() {
            skipBlank();
            char c = (char) next;
            next = read();
            return c;
        }

        public void flush() {
            try {
                os.write(cache.toString().getBytes(charset));
                os.flush();
                cache.setLength(0);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }

        public boolean hasMore() {
            skipBlank();
            return next != -1;
        }
    }

    public static class Debug {
        private boolean allowDebug;

        public Debug(boolean allowDebug) {
            this.allowDebug = allowDebug;
        }

        public void assertTrue(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (!flag) {
                fail();
            }
        }

        public void fail() {
            throw new RuntimeException();
        }

        public void assertFalse(boolean flag) {
            if (!allowDebug) {
                return;
            }
            if (flag) {
                fail();
            }
        }

        private void outputName(String name) {
            System.out.print(name + " = ");
        }

        public void debug(String name, int x) {
            if (!allowDebug) {
                return;
            }

            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, long x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, double x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, int[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, long[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, double[] x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.toString(x));
        }

        public void debug(String name, Object x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println("" + x);
        }

        public void debug(String name, Object... x) {
            if (!allowDebug) {
                return;
            }
            outputName(name);
            System.out.println(Arrays.deepToString(x));
        }
    }
}


import java.util.*;
import java.io.*;

public class Main {
	public static void main(String args[]) { new Main().WORK(); }

	Scanner in = new Scanner(System.in);
	PrintWriter out = new PrintWriter(System.out);

	final int N = (int)(2e5+10);

	class PII {
		int v, w;
		PII(int v, int w) {
			this.v = v;
			this.w = w;
		}
	}

	boolean[] vis = new boolean[N];
	int[][] up = new int[N][2], dw = new int[N][2];
	ArrayList<PII>[] G = new ArrayList[N];
	long ans = 0;

	void dfs_1(int u, int fa) {
		for(PII t:G[u]) if(t.v != fa) {
			dfs_1(t.v, u);
			if(t.w == 0) dw[u][0] += dw[t.v][0]+1;
			else dw[u][1] += dw[t.v][0]+dw[t.v][1]+1;
		}
	}

	void dfs_2(int u, int fa) {
//		out.printf("u=%d %d %d %d %d\n", u, up[u][0], up[u][1]
//				, dw[u][0], dw[u][1]);
		ans += up[u][0]+up[u][1]+dw[u][0]+dw[u][1];
		for(PII t:G[u]) if(t.v != fa) {
			if(t.w == 0) up[t.v][0] += up[u][0]+dw[u][0]-dw[t.v][0];
			else up[t.v][1] += up[u][0]+up[u][1]+
					dw[u][0]-dw[t.v][0]+dw[u][1]-dw[t.v][1];
			dfs_2(t.v, u);
		}
	}

	void WORK() {
		int n = in.nextInt();
		for(int i = 1; i <= n; i++) G[i] = new ArrayList<>();
		for(int i = 1; i < n; i++) {
			int u = in.nextInt(), v = in.nextInt(), w = in.nextInt();
			G[u].add(new PII(v, w));
			G[v].add(new PII(u, w));
		}
		dfs_1(1, 0); dfs_2(1, 0);
		out.println(ans);
		out.flush();
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class zeroonetree {

public static void main(String[] xx) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    int n = Integer.parseInt(br.readLine());
    Node[] nodes = readGraph(br, n, n - 1);
    long ways = 0;
    for (Node node : nodes) {
        for (int weight = 0; weight < 2; weight++) {
            if (node.compSize[weight] == 0) {
                node.search(weight);
                node.updateCompSize(weight);
                Node.curCompSize = 0;
                long compSize = node.compSize[weight];
                ways += compSize * (compSize - 1);
            }
        }
    }
    for (Node node : nodes) {
        if (node.compSize[0] > 1 && node.compSize[1] > 1) {
            ways += ((long) (node.compSize[0] - 1)) * (node.compSize[1] - 1);
        }
    }
    System.out.println(ways);
    br.close();

}

private static class Node {
    // 0-indexed index of the node in the Node[] returned from undirectedGraphFromEdgeList
    int ind;
    // edges of the node
    Node[] edges;
    int[] weights;
    // compSize[i] = the size of the component that uses only edges of weight i.
    int[] compSize = new int[2];
    private static int curCompSize = 0;

    private void search(int edgeWeight) {
        compSize[edgeWeight]++; // acting as boolean seen variable rn
        curCompSize++;
        for (int i = 0; i < edges.length; i++) {
            if (weights[i] == edgeWeight && edges[i].compSize[edgeWeight] == 0) {
                edges[i].search(edgeWeight);
            }
        }
    }

    private void updateCompSize(int edgeWeight) {
        compSize[edgeWeight] = curCompSize;
        for (int i = 0; i < edges.length; i++) {
            if (weights[i] == edgeWeight && edges[i].compSize[edgeWeight] != curCompSize) {
                edges[i].updateCompSize(edgeWeight);
            }
        }
    }

}

private static Node[] readGraph(BufferedReader br, int n, int m) throws IOException {
    Node[] nodes = new Node[n];
    for (int i = 0; i < n; i++) {
        nodes[i] = new Node();
        nodes[i].ind = i;
    }
    int[][] edges = new int[m][3];
    int[] n_edge = new int[n];
    for (int i = 0; i < m; i++) {
        String[] edge = br.readLine().split(" ");
        int a = Integer.parseInt(edge[0]) - 1; // assuming edges from input are 1-indexed
        int b = Integer.parseInt(edge[1]) - 1; // and assuming you want them 0-indexed
        edges[i][0] = a;
        edges[i][1] = b;
        edges[i][2] = Integer.parseInt(edge[2]);
        n_edge[a]++;
        n_edge[b]++;
    }
    for (int i = 0; i < n; i++) {
        nodes[i].edges = new Node[n_edge[i]];
        nodes[i].weights = new int[n];
    }
    for (int[] edge : edges) {
        Node a = nodes[edge[0]];
        Node b = nodes[edge[1]];
        int w = edge[2];
        a.weights[--n_edge[a.ind]] = w;
        a.edges[n_edge[a.ind]] = b;
        b.weights[--n_edge[b.ind]] = w;
        b.edges[n_edge[b.ind]] = a;
    }
    return nodes;
}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class zeroonetree {

public static void main(String[] xx) throws IOException {
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    int n = Integer.parseInt(br.readLine());
    Node[] nodes = readGraph(br, n, n - 1);
    long ways = 0;
    for (Node node : nodes) {
        for (int weight = 0; weight < 2; weight++) {
            if (node.compSize[weight] == 0) {
                node.search(weight);
                node.updateCompSize(weight);
                Node.curCompSize = 0;
                long compSize = node.compSize[weight];
                ways += compSize * (compSize - 1);
            }
        }
    }
    for (Node node : nodes) {
        if (node.compSize[0] > 1 && node.compSize[1] > 1) {
            ways += ((long) (node.compSize[0] - 1)) * (node.compSize[1] - 1);
        }
    }
    System.out.println(ways);
    br.close();

}

private static class Node {
    // 0-indexed index of the node in the Node[] returned from undirectedGraphFromEdgeList
    int ind;
    // edges of the node
    Node[] edges;
    int[] weights;
    // compSize[i] = the size of the component that uses only edges of weight i.
    int[] compSize = new int[2];
    private static int curCompSize = 0;

    private void search(int edgeWeight) {
        compSize[edgeWeight]++; // acting as boolean seen variable rn
        curCompSize++;
        for (int i = 0; i < edges.length; i++) {
            if (weights[i] == edgeWeight && edges[i].compSize[edgeWeight] == 0) {
                edges[i].search(edgeWeight);
            }
        }
    }

    private void updateCompSize(int edgeWeight) {
        compSize[edgeWeight] = curCompSize;
        for (int i = 0; i < edges.length; i++) {
            if (weights[i] == edgeWeight && edges[i].compSize[edgeWeight] != curCompSize) {
                edges[i].updateCompSize(edgeWeight);
            }
        }
    }

}

private static Node[] readGraph(BufferedReader br, int n, int m) throws IOException {
    Node[] nodes = new Node[n];
    for (int i = 0; i < n; i++) {
        nodes[i] = new Node();
        nodes[i].ind = i;
    }
    int[][] edges = new int[m][3];
    int[] n_edge = new int[n];
    for (int i = 0; i < m; i++) {
        String[] edge = br.readLine().split(" ");
        int a = Integer.parseInt(edge[0]) - 1; // assuming edges from input are 1-indexed
        int b = Integer.parseInt(edge[1]) - 1; // and assuming you want them 0-indexed
        edges[i][0] = a;
        edges[i][1] = b;
        edges[i][2] = Integer.parseInt(edge[2]);
        n_edge[a]++;
        n_edge[b]++;
    }
    for (int i = 0; i < n; i++) {
        nodes[i].edges = new Node[n_edge[i]];
        nodes[i].weights = new int[n_edge[i]];
    }
    for (int[] edge : edges) {
        Node a = nodes[edge[0]];
        Node b = nodes[edge[1]];
        int w = edge[2];
        a.weights[--n_edge[a.ind]] = w;
        a.edges[n_edge[a.ind]] = b;
        b.weights[--n_edge[b.ind]] = w;
        b.edges[n_edge[b.ind]] = a;
    }
    return nodes;
}
}


//make sure to make new file!
import java.io.*;
import java.util.*;

public class D1156{

   public static ArrayList<ArrayList<Edge>> adj;
   public static long[][] sub;
   public static long[][] dp;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      int n = Integer.parseInt(f.readLine());

      adj = new ArrayList<ArrayList<Edge>>(n+1);

      for(int k = 0; k <= n; k++) adj.add(new ArrayList<Edge>());

      for(int k = 0; k < n-1; k++){
         StringTokenizer st = new StringTokenizer(f.readLine());
         int a = Integer.parseInt(st.nextToken());
         int b = Integer.parseInt(st.nextToken());
         int c = Integer.parseInt(st.nextToken());

         adj.get(a).add(new Edge(b,c));
         adj.get(b).add(new Edge(a,c));
      }

      sub = new long[n+1][2];                          //[node][0 or 1];
      dp = new long[n+1][2];

      subdfs(1,-1);

      dpdfs(1,-1);

      int answer = 0;
      for(int k = 1; k <= n; k++){
         for(int j = 0; j <= 1; j++){
            answer+=dp[k][j];
         }
      }

      out.println(answer);

      out.close();
   }

   public static void dpdfs(int v, int p){
      dp[v][0] += sub[v][0];
      dp[v][1] += sub[v][1];

      for(Edge e : adj.get(v)){
         if(e.nei == p) continue;
         if(e.w == 0){
            dp[e.nei][0] = dp[v][0] + dp[v][1] - sub[e.nei][0] - sub[e.nei][1];
         } else {
            dp[e.nei][1] = dp[v][1] - sub[e.nei][1];
         }
         dpdfs(e.nei,v);
      }
   }

   public static void subdfs(int v, int p){

      sub[v][0] = 0L;
      sub[v][1] = 0L;

      for(Edge e : adj.get(v)){
         if(e.nei == p) continue;
         subdfs(e.nei,v);
         if(e.w == 0){
            sub[v][0] += sub[e.nei][0] + sub[e.nei][1] + 1;
         } else {
            sub[v][1] += sub[e.nei][1] + 1;
         }
      }
   }

   public static class Edge{
      int nei;
      int w;
      public Edge(int a, int b){
         nei = a;
         w = b;
      }
   }

}


//make sure to make new file!
import java.io.*;
import java.util.*;

public class D1156{

   public static ArrayList<ArrayList<Edge>> adj;
   public static long[][] sub;
   public static long[][] dp;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      int n = Integer.parseInt(f.readLine());

      adj = new ArrayList<ArrayList<Edge>>(n+1);

      for(int k = 0; k <= n; k++) adj.add(new ArrayList<Edge>());

      for(int k = 0; k < n-1; k++){
         StringTokenizer st = new StringTokenizer(f.readLine());
         int a = Integer.parseInt(st.nextToken());
         int b = Integer.parseInt(st.nextToken());
         int c = Integer.parseInt(st.nextToken());

         adj.get(a).add(new Edge(b,c));
         adj.get(b).add(new Edge(a,c));
      }

      sub = new long[n+1][2];                          //[node][0 or 1];
      dp = new long[n+1][2];

      subdfs(1,-1);

      dpdfs(1,-1);

      long answer = 0L;
      for(int k = 1; k <= n; k++){
         for(int j = 0; j <= 1; j++){
            answer+=dp[k][j];
         }
      }

      out.println(answer);

      out.close();
   }

   public static void dpdfs(int v, int p){
      dp[v][0] += sub[v][0];
      dp[v][1] += sub[v][1];

      for(Edge e : adj.get(v)){
         if(e.nei == p) continue;
         if(e.w == 0){
            dp[e.nei][0] = dp[v][0] + dp[v][1] - sub[e.nei][0] - sub[e.nei][1];
         } else {
            dp[e.nei][1] = dp[v][1] - sub[e.nei][1];
         }
         dpdfs(e.nei,v);
      }
   }

   public static void subdfs(int v, int p){

      sub[v][0] = 0L;
      sub[v][1] = 0L;

      for(Edge e : adj.get(v)){
         if(e.nei == p) continue;
         subdfs(e.nei,v);
         if(e.w == 0){
            sub[v][0] += sub[e.nei][0] + sub[e.nei][1] + 1;
         } else {
            sub[v][1] += sub[e.nei][1] + 1;
         }
      }
   }

   public static class Edge{
      int nei;
      int w;
      public Edge(int a, int b){
         nei = a;
         w = b;
      }
   }

}


//make sure to make new file!
import java.io.*;
import java.util.*;

public class D1156{

   public static ArrayList<ArrayList<Edge>> adj;
   public static int[][] sub;
   public static int[][] dp;

   public static void main(String[] args)throws IOException{
      BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
      PrintWriter out = new PrintWriter(System.out);

      int n = Integer.parseInt(f.readLine());

      adj = new ArrayList<ArrayList<Edge>>(n+1);

      for(int k = 0; k <= n; k++) adj.add(new ArrayList<Edge>());

      for(int k = 0; k < n-1; k++){
         StringTokenizer st = new StringTokenizer(f.readLine());
         int a = Integer.parseInt(st.nextToken());
         int b = Integer.parseInt(st.nextToken());
         int c = Integer.parseInt(st.nextToken());

         adj.get(a).add(new Edge(b,c));
         adj.get(b).add(new Edge(a,c));
      }

      sub = new int[n+1][2];                          //[node][0 or 1];
      dp = new int[n+1][2];

      subdfs(1,-1);

      dpdfs(1,-1);

      int answer = 0;
      for(int k = 1; k <= n; k++){
         for(int j = 0; j <= 1; j++){
            answer+=dp[k][j];
         }
      }

      out.println(answer);

      out.close();
   }

   public static void dpdfs(int v, int p){
      dp[v][0] += sub[v][0];
      dp[v][1] += sub[v][1];

      for(Edge e : adj.get(v)){
         if(e.nei == p) continue;
         if(e.w == 0){
            dp[e.nei][0] = dp[v][0] + dp[v][1] - sub[e.nei][0] - sub[e.nei][1];
         } else {
            dp[e.nei][1] = dp[v][1] - sub[e.nei][1];
         }
         dpdfs(e.nei,v);
      }
   }

   public static void subdfs(int v, int p){

      sub[v][0] = 0;
      sub[v][1] = 0;

      for(Edge e : adj.get(v)){
         if(e.nei == p) continue;
         subdfs(e.nei,v);
         if(e.w == 0){
            sub[v][0] += sub[e.nei][0] + sub[e.nei][1] + 1;
         } else {
            sub[v][1] += sub[e.nei][1] + 1;
         }
      }
   }

   public static class Edge{
      int nei;
      int w;
      public Edge(int a, int b){
         nei = a;
         w = b;
      }
   }

}


/**
 * Created by Aminul on 5/16/2019.
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D_2 {
    static boolean vis[], mark[];
    static int g[][][];
    static long count[][], ans[][];

    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        int n = in.nextInt();
        count = new long[2][2];
        ans = new long[2][2];
        int from[] = new int[n - 1], to[] = new int[n - 1], w[] = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt(), c = in.nextInt();
            from[i] = u;
            to[i] = v;
            w[i] = c;
        }
       // int ug[][] = packU(n + 1, from, to);
        g = packWU(n + 1, from, to, w);
        int centroids[] = new Centroid_Decomposition(g, 1).centroids;
        vis = new boolean[n + 1];
        mark = new boolean[n + 1];
        for (int u : centroids) {
            mark[u] = true;
            vis[u] = true;
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], +1);
            }
            ans[0][0] += count[0][0];
            ans[0][1] += count[0][1];
            ans[1][1] += count[1][1];
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
                calc(v[0], v[1], v[1]);
                dfs(v[0], v[1], v[1], +1);
            }
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
            }
            vis[u] = false;
        }

        long res = ans[0][0] + ans[0][1] + ans[1][1];
        pw.println(res);

        pw.close();
    }

    static void dfs(int u, int start, int curr, int val) {
        vis[u] = true;
        count[start][curr] += val;
        if (mark[u]) {
            vis[u] = false;
            return;
        }
        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (curr == 1 && w == 0) continue;
            if (vis[node]) continue;
            if (mark[node]) {
                count[start][curr | w] += val;
                continue;
            }
            dfs(node, start, curr | w, val);
        }
        vis[u] = false;
    }

    static void calc(int u, int start, int curr) {
        if (mark[u]) return;
        vis[u] = true;
        if (curr == 0) {
            if (start == 0) {
                ans[0][0] += count[0][0];
                ans[0][1] += count[0][1];
                ans[0][1] += count[1][1];
            } else {
                ans[0][1] += count[1][1];
            }
        } else {
            ans[1][1] += count[1][1];
        }

        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 0 && w == 1) continue;
            calc(node, start, curr & w);
        }
        vis[u] = false;
    }

    public static int[][][] packWU(int n, int[] from, int[] to, int[] w) {
        int[][][] g = new int[n][][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]][2];
        for (int i = 0; i < from.length; i++) {
            --p[from[i]];
            g[from[i]][p[from[i]]][0] = to[i];
            g[from[i]][p[from[i]]][1] = w[i];
            --p[to[i]];
            g[to[i]][p[to[i]]][0] = from[i];
            g[to[i]][p[to[i]]][1] = w[i];
        }
        return g;
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }

    static class Centroid_Decomposition {
        int g[][][];
        int[] size, par, centroids;
        int idx = 0;
        boolean[] vis;

        Centroid_Decomposition(int g[][][], int root) { // 1-based indexed, root = 1
            this.g = g;
            int n = g.length;
            size = new int[n];
            par = new int[n];
            centroids = new int[n];
            idx = 0;
            vis = new boolean[n];
            calcSize(root, 0);
            decompose(root, 0);
        }

        int calcSize(int u, int p) {
            size[u] = 1;
            for (int v[] : g[u]) {
                if (v[0] != p) {
                    size[u] += calcSize(v[0], u);
                }
            }
            return size[u];
        }

        void decompose(int u, int p) {
            int max = 0, v = -1;
            for (int e[] : g[u]) {
                int x = e[0];
                if (!vis[x] && size[x] > max) {
                    max = size[x];
                    v = x;
                }
            }
            while (max > size[u] / 2) {
                int t = size[v];
                size[v] = size[u];
                size[u] = size[v] - t;
                u = v;
                max = 0;
                for (int e[] : g[u]) {
                    int x = e[0];
                    if (!vis[x] && size[x] > max) {
                        max = size[x];
                        v = x;
                    }
                }
            }
            par[u] = p;
            vis[u] = true;
            centroids[idx++] = u;
            for (int e[] : g[u]) {
                int x = e[0];
                if (!vis[x]) {
                    decompose(x, u);
                }
            }
        }
    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;

        public FastReader(InputStream is) {
            this.is = is;
        }

        public int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

        public String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public String nextLine() {
            int c = skip();
            StringBuilder sb = new StringBuilder();
            while (!isEndOfLine(c)) {
                sb.appendCodePoint(c);
                c = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        public char readChar() {
            return (char) skip();
        }
    }
}


/**
 * Created by Aminul on 5/16/2019.
 */

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D_2 {
    static boolean vis[], mark[];
    static int g[][][];
    static int count[][] = new int[2][2], ans[][] = new int[2][2];

    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        int n = in.nextInt();
        int from[] = new int[n - 1], to[] = new int[n - 1], w[] = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt(), c = in.nextInt();
            from[i] = u;
            to[i] = v;
            w[i] = c;
        }
        int ug[][] = packU(n + 1, from, to);
        g = packWU(n + 1, from, to, w);
        int centroids[] = new Centroid_Decomposition(ug, 1).centroids;
        vis = new boolean[n + 1];
        mark = new boolean[n + 1];
        for (int u : centroids) {
            mark[u] = true;
            vis[u] = true;
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], +1);
            }
            ans[0][0] += count[0][0];
            ans[0][1] += count[0][1];
            ans[1][1] += count[1][1];
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
                calc(v[0], v[1], v[1]);
                dfs(v[0], v[1], v[1], +1);
            }
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
            }
            //debug(u, ans[0][0], ans[0][1], ans[1][1]);
            vis[u] = false;
        }

        long res = ans[0][0] + ans[0][1] + ans[1][1];
        pw.println(res);

        pw.close();
    }

    static void dfs(int u, int start, int curr, int val) {
        vis[u] = true;
        count[start][curr] += val;
        if (mark[u]) {
            vis[u] = false;
            return;
        }
        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (curr == 1 && w == 0) continue;
            if (vis[node]) continue;
            if(mark[node]) {
                count[start][curr | w] += val;
                continue;
            }
            dfs(node, start, curr | w, val);
        }
        vis[u] = false;
    }

    static void calc(int u, int start, int curr) {
        if (mark[u]) return;
        vis[u] = true;
        if (curr == 0) {
            if (start == 0) {
                ans[0][0] += count[0][0];
                ans[0][1] += count[0][1];
                ans[0][1] += count[1][1];
            }
            else {
                ans[0][1] += count[1][1];
            }
        } else {
            ans[1][1] += count[1][1];
        }

        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 0 && w == 1) continue;
            calc(node, start, curr & w);
        }
        vis[u] = false;
    }

    public static int[][][] packWU(int n, int[] from, int[] to, int[] w) {
        int[][][] g = new int[n][][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]][2];
        for (int i = 0; i < from.length; i++) {
            --p[from[i]];
            g[from[i]][p[from[i]]][0] = to[i];
            g[from[i]][p[from[i]]][1] = w[i];
            --p[to[i]];
            g[to[i]][p[to[i]]][0] = from[i];
            g[to[i]][p[to[i]]][1] = w[i];
        }
        return g;
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }

    static class Centroid_Decomposition {
        int g[][];
        int[] size, par;
        boolean[] vis;
        int centroids[], cd;

        Centroid_Decomposition(int g[][], int root) { // 1-based indexed, root = 1
            this.g = g;
            int n = g.length;
            size = new int[n];
            par = new int[n];
            vis = new boolean[n];
            centroids = new int[n - 1];
            cd = 0;
            calcSize(root, 0);
            decompose(root, 0);
        }

        int calcSize(int u, int p) {
            size[u] = 1;
            for (int v : g[u]) {
                if (v != p) {
                    size[u] += calcSize(v, u);
                }
            }
            return size[u];
        }

        void decompose(int u, int p) {
            int max = 0, v = -1;
            for (int x : g[u]) {
                if (!vis[x] && size[x] > max) {
                    max = size[x];
                    v = x;
                }
            }
            while (max > size[u] / 2) {
                int t = size[v];
                size[v] = size[u];
                size[u] = size[v] - t;
                u = v;
                max = 0;
                for (int x : g[u]) {
                    if (!vis[x] && size[x] > max) {
                        max = size[x];
                        v = x;
                    }
                }
            }
            centroids[cd++] = u;
            par[u] = p;
            vis[u] = true;
            for (int x : g[u]) {
                if (!vis[x]) {
                    decompose(x, u);
                }
            }
        }

        void update(int u) {
            for (int v = u; v != 0; v = par[v]) {
                //int dist = lca.dist(u, v);
                //nearest[v] = min(nearest[v], dist);
                //do update
            }
        }

        int query(int u) {
            int min = Integer.MAX_VALUE;
            for (int v = u; v != 0; v = par[v]) {
                //int dist = lca.dist(u, v);
                //min = min(min, dist + nearest[v]);
                //do query
            }
            return min;
        }

    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;

        public FastReader(InputStream is) {
            this.is = is;
        }

        public int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

        public String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public String nextLine() {
            int c = skip();
            StringBuilder sb = new StringBuilder();
            while (!isEndOfLine(c)) {
                sb.appendCodePoint(c);
                c = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        public char readChar() {
            return (char) skip();
        }
    }
}


/**
 * Created by Aminul on 5/16/2019.
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D_2_test {
    static boolean vis[], mark[];
    static int g[][][];
    static long count[][], ans[][];

    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        int n = in.nextInt();
        count = new long[2][2];
        ans = new long[2][2];
        int from[] = new int[n - 1], to[] = new int[n - 1], w[] = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt(), c = in.nextInt();
            from[i] = u;
            to[i] = v;
            w[i] = c;
        }
        int ug[][] = packU(n + 1, from, to);
        g = packWU(n + 1, from, to, w);
        //int centroids[] = new Centroid_Decomposition(ug, 1).centroids;
        int ctree[] = buildCentroidTree(ug, 1);
        int centroids[] = cd;
       // debug(cd, ctree);
        vis = new boolean[n + 1];
        mark = new boolean[n + 1];
        for (int u : centroids) {
            mark[u] = true;
            vis[u] = true;
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], +1);
            }
            ans[0][0] += count[0][0];
            ans[0][1] += count[0][1];
            ans[1][1] += count[1][1];
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
                calc(v[0], v[1], v[1]);
                dfs(v[0], v[1], v[1], +1);
            }
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
            }
            vis[u] = false;
        }

        long res = ans[0][0] + ans[0][1] + ans[1][1];
        pw.println(res);

        pw.close();
    }

    static void dfs(int u, int start, int curr, int val) {
        vis[u] = true;
        count[start][curr] += val;
        if (mark[u]) {
            vis[u] = false;
            return;
        }
        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (curr == 1 && w == 0) continue;
            if (vis[node]) continue;
            if (mark[node]) {
                count[start][curr | w] += val;
                continue;
            }
            dfs(node, start, curr | w, val);
        }
        vis[u] = false;
    }

    static void calc(int u, int start, int curr) {
        if (mark[u]) return;
        vis[u] = true;
        if (curr == 0) {
            if (start == 0) {
                ans[0][0] += count[0][0];
                ans[0][1] += count[0][1];
                ans[0][1] += count[1][1];
            } else {
                ans[0][1] += count[1][1];
            }
        } else {
            ans[1][1] += count[1][1];
        }

        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 0 && w == 1) continue;
            calc(node, start, curr & w);
        }
        vis[u] = false;
    }

    public static int[][][] packWU(int n, int[] from, int[] to, int[] w) {
        int[][][] g = new int[n][][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]][2];
        for (int i = 0; i < from.length; i++) {
            --p[from[i]];
            g[from[i]][p[from[i]]][0] = to[i];
            g[from[i]][p[from[i]]][1] = w[i];
            --p[to[i]];
            g[to[i]][p[to[i]]][0] = from[i];
            g[to[i]][p[to[i]]][1] = w[i];
        }
        return g;
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }
    static int cd[], idx = 0;
    public static int[] buildCentroidTree(int[][] g, int root) {
        int n = g.length;
        int[] ctpar = new int[n];
        Arrays.fill(ctpar, -1);
        cd = new int[n];
        buildCentroidTree(g, root, new boolean[n], new int[n], new int[n], new int[n], ctpar);
        return ctpar;
    }

    private static int buildCentroidTree(int[][] g, int root, boolean[] sed, int[] par, int[] ord, int[] des, int[] ctpar)
    {
        // parent and level-order
        ord[0] = root;
        par[root] = -1;
        int r = 1;
        for(int p = 0;p < r;p++) {
            int cur = ord[p];
            for(int nex : g[cur]){
                if(par[cur] != nex && !sed[nex]){
                    ord[r++] = nex;
                    par[nex] = cur;
                }
            }
        }
        // if(r == 1)return;

        // DP and find a separator
        int sep = -1; // always exists
        outer:
        for(int i = r-1;i >= 0;i--){
            int cur = ord[i];
            des[cur] = 1;
            for(int e : g[cur]){
                if(par[cur] != e && !sed[e])des[cur] += des[e];
            }
            if(r-des[cur] <= r/2){
                for(int e : g[cur]){
                    if(par[cur] != e && !sed[e] && des[e] >= r/2+1)continue outer;
                }
                sep = cur;
                break;
            }
        }

        sed[sep] = true;
        cd[idx++] = sep;
        for(int e : g[sep]){
            if(!sed[e])ctpar[buildCentroidTree(g, e, sed, par, ord, des, ctpar)] = sep;
        }
        return sep;
    }

    static class Centroid_Decomposition {
        int g[][];
        int[] size, par, centroids;
        int idx = 0;
        boolean[] vis;

        Centroid_Decomposition(int g[][], int root) { // 1-based indexed, root = 1
            this.g = g;
            int n = g.length;
            size = new int[n];
            par = new int[n];
            centroids = new int[n];
            idx = 0;
            vis = new boolean[n];
            calcSize(root, 0);
            decompose(root, 0);
        }

        int calcSize(int u, int p) {
            size[u] = 1;
            for (int v : g[u]) {
                if (v != p) {
                    size[u] += calcSize(v, u);
                }
            }
            return size[u];
        }

        void decompose(int u, int p) {
            int max = 0, v = -1;
            for (int x : g[u]) {
                if (!vis[x] && size[x] > max) {
                    max = size[x];
                    v = x;
                }
            }
            while (max > size[u] / 2) {
                int t = size[v];
                size[v] = size[u];
                size[u] = size[v] - t;
                u = v;
                max = 0;
                for (int x : g[u]) {
                    if (!vis[x] && size[x] > max) {
                        max = size[x];
                        v = x;
                    }
                }
            }
            par[u] = p;
            vis[u] = true;
            centroids[idx++] = u;
            for (int x : g[u]) {
                if (!vis[x]) {
                    decompose(x, u);
                }
            }
        }
    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;

        public FastReader(InputStream is) {
            this.is = is;
        }

        public int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

        public String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public String nextLine() {
            int c = skip();
            StringBuilder sb = new StringBuilder();
            while (!isEndOfLine(c)) {
                sb.appendCodePoint(c);
                c = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        public char readChar() {
            return (char) skip();
        }
    }
}


/**
 * Created by Aminul on 5/16/2019.
 */

import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D_2 {
    static boolean vis[], mark[];
    static int g[][][];
    static long count[][], ans[][];

    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        int n = in.nextInt();
        count = new long[2][2];
        ans = new long[2][2];
        int from[] = new int[n - 1], to[] = new int[n - 1], w[] = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt(), c = in.nextInt();
            from[i] = u;
            to[i] = v;
            w[i] = c;
        }
        int ug[][] = packU(n + 1, from, to);
        g = packWU(n + 1, from, to, w);
        int centroids[] = new Centroid_Decomposition(ug, 1).centroids;
        vis = new boolean[n + 1];
        mark = new boolean[n + 1];
        for (int u : centroids) {
            mark[u] = true;
            vis[u] = true;
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], +1);
            }
            ans[0][0] += count[0][0];
            ans[0][1] += count[0][1];
            ans[1][1] += count[1][1];
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
                calc(v[0], v[1], v[1]);
                dfs(v[0], v[1], v[1], +1);
            }
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
            }
            vis[u] = false;
        }

        long res = ans[0][0] + ans[0][1] + ans[1][1];
        pw.println(res);

        pw.close();
    }

    static void dfs(int u, int start, int curr, int val) {
        vis[u] = true;
        count[start][curr] += val;
        if (mark[u]) {
            vis[u] = false;
            return;
        }
        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (curr == 1 && w == 0) continue;
            if (vis[node]) continue;
            if (mark[node]) {
                count[start][curr | w] += val;
                continue;
            }
            dfs(node, start, curr | w, val);
        }
        vis[u] = false;
    }

    static void calc(int u, int start, int curr) {
        if (mark[u]) return;
        vis[u] = true;
        if (curr == 0) {
            if (start == 0) {
                ans[0][0] += count[0][0];
                ans[0][1] += count[0][1];
                ans[0][1] += count[1][1];
            } else {
                ans[0][1] += count[1][1];
            }
        } else {
            ans[1][1] += count[1][1];
        }

        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 0 && w == 1) continue;
            calc(node, start, curr & w);
        }
        vis[u] = false;
    }

    public static int[][][] packWU(int n, int[] from, int[] to, int[] w) {
        int[][][] g = new int[n][][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]][2];
        for (int i = 0; i < from.length; i++) {
            --p[from[i]];
            g[from[i]][p[from[i]]][0] = to[i];
            g[from[i]][p[from[i]]][1] = w[i];
            --p[to[i]];
            g[to[i]][p[to[i]]][0] = from[i];
            g[to[i]][p[to[i]]][1] = w[i];
        }
        return g;
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }

    static class Centroid_Decomposition {
        int g[][];
        int[] size, par, centroids;
        int idx = 0;
        boolean[] vis;

        Centroid_Decomposition(int g[][], int root) { // 1-based indexed, root = 1
            this.g = g;
            int n = g.length;
            size = new int[n];
            par = new int[n];
            centroids = new int[n];
            idx = 0;
            vis = new boolean[n];
            calcSize(root, 0);
            decompose(root, 0);
        }

        int calcSize(int u, int p) {
            size[u] = 1;
            for (int v : g[u]) {
                if (v != p) {
                    size[u] += calcSize(v, u);
                }
            }
            return size[u];
        }

        void decompose(int u, int p) {
            int max = 0, v = -1;
            for (int x : g[u]) {
                if (!vis[x] && size[x] > max) {
                    max = size[x];
                    v = x;
                }
            }
            while (max > size[u] / 2) {
                int t = size[v];
                size[v] = size[u];
                size[u] = size[v] - t;
                u = v;
                max = 0;
                for (int x : g[u]) {
                    if (!vis[x] && size[x] > max) {
                        max = size[x];
                        v = x;
                    }
                }
            }
            par[u] = p;
            vis[u] = true;
            centroids[idx++] = u;
            for (int x : g[u]) {
                if (!vis[x]) {
                    decompose(x, u);
                }
            }
        }
    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;

        public FastReader(InputStream is) {
            this.is = is;
        }

        public int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

        public String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public String nextLine() {
            int c = skip();
            StringBuilder sb = new StringBuilder();
            while (!isEndOfLine(c)) {
                sb.appendCodePoint(c);
                c = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        public char readChar() {
            return (char) skip();
        }
    }
}


/**
 * Created by Aminul on 5/16/2019.
 */

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D {
    static boolean vis[], mark[];
    static int g[][][];
    static int count[][] = new int[2][2], ans[][] = new int[2][2];

    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);
        try {
            in = new FastReader(new FileInputStream("in.txt"));
            //pw = new PrintWriter("a.txt");
        } catch (Exception e) {
        }

        int n = in.nextInt();
        int from[] = new int[n - 1], to[] = new int[n - 1], w[] = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt(), c = in.nextInt();
            from[i] = u;
            to[i] = v;
            w[i] = c;
        }
        int ug[][] = packU(n + 1, from, to);
        g = packWU(n + 1, from, to, w);
        int centroids[] = new Centroid_Decomposition(ug, 1).centroids;
        vis = new boolean[n + 1];
        mark = new boolean[n + 1];
        for (int u : centroids) {
            mark[u] = true;
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], +1);
            }
            ans[0][0] += count[0][0];
            ans[0][1] += count[0][1];
            ans[1][1] += count[1][1];
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
                calc(v[0], v[1], v[1]);
                dfs(v[0], v[1], v[1], +1);
            }
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
            }
            //debug(u, ans[0][0], ans[0][1], ans[1][1]);
        }

        long res = ans[0][0] + ans[0][1] + ans[1][1];
        pw.println(res);

        pw.close();
    }

    static void dfs(int u, int start, int curr, int val) {
        vis[u] = true;
        count[start][curr] += val;
        if (mark[u]) {
            vis[u] = false;
            return;
        }
        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 1 && w == 0) continue;
            dfs(node, start, curr | w, val);
        }
        vis[u] = false;
    }

    static void calc(int u, int start, int curr) {
        if (mark[u]) return;
        vis[u] = true;
        if (curr == 0) {
            if (start == 0) {
                ans[0][0] += count[0][0];
                ans[0][0] += count[0][1];
                ans[0][0] += count[1][1];
            }
            else {
                ans[0][1] += count[1][1];
            }
        } else {
            ans[1][1] += count[1][1];
        }

        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 0 && w == 1) continue;
            calc(node, start, curr & w);
        }
        vis[u] = false;
    }

    public static int[][][] packWU(int n, int[] from, int[] to, int[] w) {
        int[][][] g = new int[n][][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]][2];
        for (int i = 0; i < from.length; i++) {
            --p[from[i]];
            g[from[i]][p[from[i]]][0] = to[i];
            g[from[i]][p[from[i]]][1] = w[i];
            --p[to[i]];
            g[to[i]][p[to[i]]][0] = from[i];
            g[to[i]][p[to[i]]][1] = w[i];
        }
        return g;
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }

    static class Centroid_Decomposition {
        int g[][];
        int[] size, par;
        boolean[] vis;
        int centroids[], cd;

        Centroid_Decomposition(int g[][], int root) { // 1-based indexed, root = 1
            this.g = g;
            int n = g.length;
            size = new int[n];
            par = new int[n];
            vis = new boolean[n];
            centroids = new int[n - 1];
            cd = 0;
            calcSize(root, 0);
            decompose(root, 0);
        }

        int calcSize(int u, int p) {
            size[u] = 1;
            for (int v : g[u]) {
                if (v != p) {
                    size[u] += calcSize(v, u);
                }
            }
            return size[u];
        }

        void decompose(int u, int p) {
            int max = 0, v = -1;
            for (int x : g[u]) {
                if (!vis[x] && size[x] > max) {
                    max = size[x];
                    v = x;
                }
            }
            while (max > size[u] / 2) {
                int t = size[v];
                size[v] = size[u];
                size[u] = size[v] - t;
                u = v;
                max = 0;
                for (int x : g[u]) {
                    if (!vis[x] && size[x] > max) {
                        max = size[x];
                        v = x;
                    }
                }
            }
            centroids[cd++] = u;
            par[u] = p;
            vis[u] = true;
            for (int x : g[u]) {
                if (!vis[x]) {
                    decompose(x, u);
                }
            }
        }

        void update(int u) {
            for (int v = u; v != 0; v = par[v]) {
                //int dist = lca.dist(u, v);
                //nearest[v] = min(nearest[v], dist);
                //do update
            }
        }

        int query(int u) {
            int min = Integer.MAX_VALUE;
            for (int v = u; v != 0; v = par[v]) {
                //int dist = lca.dist(u, v);
                //min = min(min, dist + nearest[v]);
                //do query
            }
            return min;
        }

    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;

        public FastReader(InputStream is) {
            this.is = is;
        }

        public int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

        public String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public String nextLine() {
            int c = skip();
            StringBuilder sb = new StringBuilder();
            while (!isEndOfLine(c)) {
                sb.appendCodePoint(c);
                c = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        public char readChar() {
            return (char) skip();
        }
    }
}


/**
 * Created by Aminul on 5/16/2019.
 */

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.InputMismatchException;

public class D {
    static boolean vis[], mark[];
    static int g[][][];
    static int count[][] = new int[2][2], ans[][] = new int[2][2];

    public static void main(String[] args) throws Exception {
        FastReader in = new FastReader(System.in);
        PrintWriter pw = new PrintWriter(System.out);

        int n = in.nextInt();
        int from[] = new int[n - 1], to[] = new int[n - 1], w[] = new int[n - 1];
        for (int i = 0; i < n - 1; i++) {
            int u = in.nextInt(), v = in.nextInt(), c = in.nextInt();
            from[i] = u;
            to[i] = v;
            w[i] = c;
        }
        int ug[][] = packU(n + 1, from, to);
        g = packWU(n + 1, from, to, w);
        int centroids[] = new Centroid_Decomposition(ug, 1).centroids;
        vis = new boolean[n + 1];
        mark = new boolean[n + 1];
        for (int u : centroids) {
            mark[u] = true;
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], +1);
            }
            ans[0][0] += count[0][0];
            ans[0][1] += count[0][1];
            ans[1][1] += count[1][1];
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
                calc(v[0], v[1], v[1]);
                dfs(v[0], v[1], v[1], +1);
            }
            for (int v[] : g[u]) {
                dfs(v[0], v[1], v[1], -1);
            }
        }

        long res = ans[0][1] + (ans[0][0]) + (ans[1][1]);
        pw.println(res);

        pw.close();
    }

    static void dfs(int u, int start, int curr, int val) {
        vis[u] = true;
        count[start][curr] += val;
        if (mark[u]) {
            vis[u] = false;
            return;
        }
        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 1 && w == 0) continue;
            dfs(node, start, curr | w, val);
        }
        vis[u] = false;
    }

    static void calc(int u, int start, int curr) {
        if (mark[u]) return;
        vis[u] = true;
        if (curr == 0) {
            if (start == 0) {
                ans[0][0] += count[0][0];
            }
            ans[0][1] += count[1][1];
        } else {
            ans[1][1] += count[1][1];
        }

        for (int v[] : g[u]) {
            int node = v[0], w = v[1];
            if (mark[node] || vis[node]) continue;
            if (curr == 0 && w == 1) continue;
            calc(node, start, curr & w);
        }
        vis[u] = false;
    }

    public static int[][][] packWU(int n, int[] from, int[] to, int[] w) {
        int[][][] g = new int[n][][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]][2];
        for (int i = 0; i < from.length; i++) {
            --p[from[i]];
            g[from[i]][p[from[i]]][0] = to[i];
            g[from[i]][p[from[i]]][1] = w[i];
            --p[to[i]];
            g[to[i]][p[to[i]]][0] = from[i];
            g[to[i]][p[to[i]]][1] = w[i];
        }
        return g;
    }

    static int[][] packU(int n, int[] from, int[] to) {
        int[][] g = new int[n][];
        int[] p = new int[n];
        for (int f : from)
            p[f]++;
        for (int t : to)
            p[t]++;
        for (int i = 0; i < n; i++)
            g[i] = new int[p[i]];
        for (int i = 0; i < from.length; i++) {
            g[from[i]][--p[from[i]]] = to[i];
            g[to[i]][--p[to[i]]] = from[i];
        }
        return g;
    }

    static void debug(Object... obj) {
        System.err.println(Arrays.deepToString(obj));
    }

    static class Centroid_Decomposition {
        int g[][];
        int[] size, par;
        boolean[] vis;
        int centroids[], cd;

        Centroid_Decomposition(int g[][], int root) { // 1-based indexed, root = 1
            this.g = g;
            int n = g.length;
            size = new int[n];
            par = new int[n];
            vis = new boolean[n];
            centroids = new int[n - 1];
            cd = 0;
            calcSize(root, 0);
            decompose(root, 0);
        }

        int calcSize(int u, int p) {
            size[u] = 1;
            for (int v : g[u]) {
                if (v != p) {
                    size[u] += calcSize(v, u);
                }
            }
            return size[u];
        }

        void decompose(int u, int p) {
            int max = 0, v = -1;
            for (int x : g[u]) {
                if (!vis[x] && size[x] > max) {
                    max = size[x];
                    v = x;
                }
            }
            while (max > size[u] / 2) {
                int t = size[v];
                size[v] = size[u];
                size[u] = size[v] - t;
                u = v;
                max = 0;
                for (int x : g[u]) {
                    if (!vis[x] && size[x] > max) {
                        max = size[x];
                        v = x;
                    }
                }
            }
            centroids[cd++] = u;
            par[u] = p;
            vis[u] = true;
            for (int x : g[u]) {
                if (!vis[x]) {
                    decompose(x, u);
                }
            }
        }

        void update(int u) {
            for (int v = u; v != 0; v = par[v]) {
                //int dist = lca.dist(u, v);
                //nearest[v] = min(nearest[v], dist);
                //do update
            }
        }

        int query(int u) {
            int min = Integer.MAX_VALUE;
            for (int v = u; v != 0; v = par[v]) {
                //int dist = lca.dist(u, v);
                //min = min(min, dist + nearest[v]);
                //do query
            }
            return min;
        }

    }

    static class FastReader {
        InputStream is;
        private byte[] inbuf = new byte[1024];
        private int lenbuf = 0, ptrbuf = 0;

        public FastReader(InputStream is) {
            this.is = is;
        }

        public int readByte() {
            if (lenbuf == -1) throw new InputMismatchException();
            if (ptrbuf >= lenbuf) {
                ptrbuf = 0;
                try {
                    lenbuf = is.read(inbuf);
                } catch (IOException e) {
                    throw new InputMismatchException();
                }
                if (lenbuf <= 0) return -1;
            }
            return inbuf[ptrbuf++];
        }

        public boolean isSpaceChar(int c) {
            return !(c >= 33 && c <= 126);
        }

        private boolean isEndOfLine(int c) {
            return c == '\n' || c == '\r' || c == -1;
        }

        public int skip() {
            int b;
            while ((b = readByte()) != -1 && isSpaceChar(b)) ;
            return b;
        }

        public String next() {
            int b = skip();
            StringBuilder sb = new StringBuilder();
            while (!(isSpaceChar(b))) {
                sb.appendCodePoint(b);
                b = readByte();
            }
            return sb.toString();
        }

        public String nextLine() {
            int c = skip();
            StringBuilder sb = new StringBuilder();
            while (!isEndOfLine(c)) {
                sb.appendCodePoint(c);
                c = readByte();
            }
            return sb.toString();
        }

        public int nextInt() {
            int num = 0, b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }
            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public long nextLong() {
            long num = 0;
            int b;
            boolean minus = false;
            while ((b = readByte()) != -1 && !((b >= '0' && b <= '9') || b == '-')) ;
            if (b == '-') {
                minus = true;
                b = readByte();
            }

            while (true) {
                if (b >= '0' && b <= '9') {
                    num = (num << 3) + (num << 1) + (b - '0');
                } else {
                    return minus ? -num : num;
                }
                b = readByte();
            }
        }

        public double nextDouble() {
            return Double.parseDouble(next());
        }

        public char[] next(int n) {
            char[] buf = new char[n];
            int b = skip(), p = 0;
            while (p < n && !(isSpaceChar(b))) {
                buf[p++] = (char) b;
                b = readByte();
            }
            return n == p ? buf : Arrays.copyOf(buf, p);
        }

        public char readChar() {
            return (char) skip();
        }
    }
}