import std.stdio, std.conv, std.string;
import std.array, std.range, std.algorithm, std.container;
import std.math, std.random, std.bigint, std.datetime, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

int DEBUG_LEVEL = 0;
void print()(){ writeln(""); }
void print(T, A ...)(T t, lazy A a){ write(t), print(a); }
void print(int level, T, A ...)(T t, lazy A a){ if(level <= DEBUG_LEVEL) print(t, a); }

void main(string[] args){
	if(args.length > 1 && args[1] == "-debug"){
		if(args.length > 2 && args[2].isNumeric) DEBUG_LEVEL = args[2].to!int;
		else DEBUG_LEVEL = 1;
	}
	
	long n = read.to!long;
	long m = read.to!long;
	
	Node[] nodes;
	foreach(i; 0 .. n) nodes ~= new Node(i, 0);
	
	foreach(nd; nodes){
		nd.group = new Group(nd);
	}
	
	Edge[] edges;
	foreach(i; 0 .. m){
		long x = read.to!long - 1;
		long y = read.to!long - 1;
		long z = read.to!long - 1;
		edges ~= new Edge(nodes[x], nodes[y], i);
	}
	
	foreach(ed; edges){
		if(ed.node1.group.id != ed.node2.group.id){
			ed.node1.group.eat(ed.node2.group);
		}
	}
	
	long ans;
	foreach(nd; nodes) if(nd.group.id == nd.id) ans += 1;
	
	ans.writeln;
	
}


class Edge{
	Node node1;
	Node node2;
	long value;
	this(Node node1, Node node2, long value){
		this.node1 = node1, this.node2 = node2;
		this.value = value;
	}
}

class Node{
	long id;
	long value;
	Group group;
	this(long id, long value){
		this.id = id;
		this.value = value;
	}
}

class Group{
	long value;
	long pendingEdgeCount;
	long id;
	Node[] nodes;
	this(Node node){
		this.id = node.id;
		this.nodes = [node];
		this.value = node.value;
	}
	void eat(Group gp){
		if(gp.nodes.length > this.nodes.length) gp.eat(this);
		else{
			foreach(nd; gp.nodes){
				this.nodes ~= nd;
				nd.group = this;
				this.value += nd.value;
			}
			this.pendingEdgeCount += gp.pendingEdgeCount;
		}
	}
}

