import java.awt.List;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Map;
import java.util.Scanner;
import java.util.StringTokenizer;

public class metro_nk {

	BufferedReader in;
	StringTokenizer str;
	PrintWriter out;

	String next() throws IOException {
		String help;
		while ((str == null) || (!str.hasMoreTokens())) {
			help = in.readLine();
			if (help == null) {
				return null;
			}
			str = new StringTokenizer(help);
		}
		return str.nextToken();
	}

	int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	static int MAXM = 200000;
	static int MAXN = 100000;
	HashMap<Integer, HashSet<Integer>> Edges;
	int[] used;
	HashSet<Integer>[] toColor;
	int[] col;
	edge[] EdgeNSort;
	edge[] SortEdges;

	void dfs(int a, int c) {
		if (used[a] == c)
			return;
		used[a] = c;
		if (Edges.get(a) != null)
			for (int p : Edges.get(a)) {
				dfs(p,c);
			}
	}

	public class edge {
		int beg;
		int end;
		int color;

		edge(int beg, int end, int color) {
			this.beg = beg;
			this.end = end;
			this.color = color;
		}

	}

	public void solve() throws IOException {
		in = new BufferedReader(new FileReader("metro.in"));
		int n = nextInt();
		int m = nextInt();
		myAssert(1 <= n && n <= MAXN, "n = " + n + " is not in range [1, "
				+ MAXN + "]");
		myAssert(1 <= m && m <= MAXM, "m = " + m + " is not in range [1, "
				+ MAXM + "]");
		int k = nextInt();
		myAssert(1 <= k && k <= MAXM, "k = " + m + " is not in range [1, "
				+ MAXM + "]");
		Edges = new HashMap<Integer, HashSet<Integer>>();
		// for (int i = 0; i < n; i++) {
		// Edges[i] = new HashSet<Integer>();
		// }
		used = new int[n];
		Arrays.fill(used,-1);
		toColor = new HashSet[k];
		for (int i = 0; i < k; i++) {
			toColor[i] = new HashSet<Integer>();
		}

		EdgeNSort = new edge[m];
		SortEdges = new edge[m];
		col = new int[k];

		for (int i = 0; i < m; i++) {
			int a = nextInt();
			myAssert(1 <= a && a <= MAXM, "Vertex " + a
					+ " is out of range [1, " + MAXM + "]");
			int b = nextInt();
			myAssert(1 <= b && b <= MAXM, "Vertex " + b
					+ " is out of range [1, " + MAXM + "]");
			int c = nextInt();
			myAssert(1 <= b && b <= MAXM, "Color " + c
					+ " is out of range [1, " + MAXM + "]");
			EdgeNSort[i] = new edge(a, b, c - 1);
			col[c - 1]++;
		}
		int[] color = new int[k];
		color[0] = 0;
		for (int i = 1; i < k; i++) {
			color[i] = color[i - 1] + col[i - 1];
		}
		for (int i = 0; i < m; i++) {
			SortEdges[color[EdgeNSort[i].color]] = EdgeNSort[i];
			color[EdgeNSort[i].color]++;
		}
		color = new int[k + 1];
		out = new PrintWriter("metro.out");
		int p = 0;
		for (int c = 0; c < k; c++) {
			Edges = new HashMap<Integer, HashSet<Integer>>();
			while (p < m
					&& (SortEdges[p].color == c)) {
				int a = SortEdges[p].beg;
				int b = SortEdges[p].end;
				toColor[c].add(a - 1);
				toColor[c].add(b - 1);
				if (Edges.get(a - 1) == null)
					Edges.put(a - 1, new HashSet<Integer>());
				Edges.get(a - 1).add(b - 1);
				if (Edges.get(b - 1) == null)
					Edges.put(b - 1, new HashSet<Integer>());
				Edges.get(b - 1).add(a - 1);
				p++;
			}
			int ans = 0;
			for (int i : toColor[c]) {
				if (used[i] != c) {
					dfs(i, c);
					ans++;
				}
			}
			out.println(ans);
		}
		out.close();
	}

	static void myAssert(boolean b, String string) {
		if (!b) {
			throw new AssertionError(string);
		}
	}

	public static void main(String[] args) throws IOException {
		new metro_nk().solve();
	}
}
