Problem:
Score : 500 points

Problem Statement

There are N cards placed face down in a row. On each card, an integer 1 or 2 is written.

Let A_i be the integer written on the i-th card.

Your objective is to guess A_1, A_2, ..., A_N correctly.

You know the following facts:

For each i = 1, 2, ..., M, the value A_{X_i} + A_{Y_i} + Z_i is an even number.

You are a magician and can use the following magic any number of times:

Magic: Choose one card and know the integer A_i written on it. The cost of using this magic is 1.

What is the minimum cost required to determine all of A_1, A_2, ..., A_N?

It is guaranteed that there is no contradiction in given input.

Constraints

All values in input are integers.

2 \leq N \leq 10^5

1 \leq M \leq 10^5

1 \leq X_i < Y_i \leq N

1 \leq Z_i \leq 100

The pairs (X_i, Y_i) are distinct.

There is no contradiction in input. (That is, there exist integers A_1, A_2, ..., A_N that satisfy the conditions.)

Input

Input is given from Standard Input in the following format:

N M
X_1 Y_1 Z_1
X_2 Y_2 Z_2
\vdots
X_M Y_M Z_M

Output

Print the minimum total cost required to determine all of A_1, A_2, ..., A_N.

Sample Input 1

3 1
1 2 1

Sample Output 1

2

You can determine all of A_1, A_2, A_3 by using the magic for the first and third cards.

Sample Input 2

6 5
1 2 1
2 3 2
1 3 3
4 5 4
5 6 5

Sample Output 2

2

Sample Input 3

100000 1
1 100000 100

Sample Output 3

99999

Solution in C++14 (GCC 5.4.1) (judge verdict: Accepted)

#ifdef __GNUC__ 
#include <bits/stdc++.h>
auto & inputdatastream = std::cin;
#else
std::ifstream inputdatastream;
#endif
#include <boost/multiprecision/cpp_int.hpp>
#include <boost/dynamic_bitset.hpp>
#include <boost/preprocessor.hpp>
#include <boost/mpl/int.hpp>

using namespace std;
#define ALL(v) std::begin(v),std::end(v)
#define RALL(v) std::rbegin(v),std::rend(v)
using u6 = std::uint64_t;
using u3 = std::uint32_t;
constexpr u6 moduloNo = 1'000'000'000 + 7; //' 1e9 + 7
#define DEFVALUE1(r,type,name) type name;
#define DEFINIT0(r,type,name) in >> name;
#define DEFINIT1(r,size,name) name.resize(size);
#define DEFINITER template <typename T, typename In> void init(const T &, In &) {}
#define DEF_TYPEEXTSELECTOR(fnext,tpl)BOOST_PP_IF(BOOST_PP_TUPLE_ELEM(0, fnext)  ,BOOST_PP_TUPLE_ELEM(2, fnext),BOOST_PP_TUPLE_ELEM(0, tpl) )
#define DEFVALUEIMPL(r,fnext,tpl) BOOST_PP_LIST_FOR_EACH(BOOST_PP_TUPLE_ELEM(1,fnext),DEF_TYPEEXTSELECTOR(fnext,tpl), BOOST_PP_TUPLE_TO_LIST(BOOST_PP_TUPLE_POP_FRONT(tpl)))
#define DEFVALUES(expr) DEFIMPL(expr,0,DEFINIT0,0,_)
#define DEFIMPL(expr,deftypeindex,initcode,c,ext)																									\
	BOOST_PP_SEQ_FOR_EACH(DEFVALUEIMPL,(0,DEFVALUE1,_),BOOST_PP_VARIADIC_SEQ_TO_SEQ(expr))															\
			template <typename In> decltype(auto) init(boost::mpl::int_<deftypeindex> ,In & in){													\
				BOOST_PP_SEQ_FOR_EACH(DEFVALUEIMPL,(c,initcode,ext),BOOST_PP_VARIADIC_SEQ_TO_SEQ(expr));return in;}
#define DEFVECS(size,expr)  DEFIMPL(expr,1,DEFINIT1,1,size)
#define DEFSTRUCT(name,...) struct name{DEFINITER;__VA_ARGS__ ;friend std::istream & operator>>(std::istream & in,name & target){				\
	target.init(boost::mpl::int_<0> (),in);target.init(boost::mpl::int_<1>() ,in);return in;} }

template <typename T>
struct invecT {
	decltype(auto) begin()const {
		return std::istream_iterator<T>(inputdatastream);
	}
	decltype(auto) end()const {
		return std::istream_iterator<T>();
	}
};
template <typename T>invecT<T> invec;

DEFSTRUCT(datatype,
	DEFVALUES((int, x, y, z))
);


struct Calc {
	DEFINITER;
	/*******************************************************************************/
	DEFVALUES(
		(int,N,M)
	);
	DEFVECS(N+1 , (vector<int>, v));
	auto calc() {
		int dup = 0;
		vector<int> updateindex;
		auto fn=[&,this](int c) {
			if (!v[c])v[c] = c;
			do{
				updateindex.push_back(c);
				c = v[c]; 
			} while (v[c] != c);
			return c;
		};
		for (auto d : invec<datatype>) {
			int l=fn(d.x);int r= fn(d.y);
			int minval=l;
			if (l == r)++dup;
			else if (l < r)updateindex.push_back(r);
			else { updateindex.push_back(l); minval = r; }
			for (auto i : updateindex)v[i] = minval;
			updateindex.clear();
		}
		return N-M+dup;
	}
	/*******************************************************************************/
};
Calc calc;

int main() {
	ios::sync_with_stdio(false);cin.tie(0);
#ifndef __GNUC__ 
	inputdatastream.open("inputdata.txt");
#endif
	calc.init(boost::mpl::int_<0>(),inputdatastream);
	calc.init(boost::mpl::int_<1>(),inputdatastream);
	cout << calc.calc() << endl;
}