CodeEff/ECCO huggingface dataset:
# Original solution
import sys 
N=int(eval(input()))
L=list(map(int,sys.stdin.readline().split()))
counter=0
L.sort()
for i,A in enumerate(L[:-2]):
    for j,B in enumerate(L[i+1:-1],i+1):
        l=j
        r=len(L)-1
        c=(r+l)//2
        while abs(r-l)>1:    
            if A>abs(L[c]-B):
                b=c
                c=(r+c)//2
                l=b
            else:
                b=c
                c=(c+l)//2
                r=b
        if A-abs(L[l]-B)>0 and A-abs(L[r]-B)>0:
            c=r
        elif A-abs(L[l]-B)>0 and A-abs(L[r]-B)<0:
            c=l
        if A>abs(L[c]-B):
            counter+=c-j
print(counter)
    



# Optimized solution

N=int(eval(input()))
L=list(map(int,input().split()))
counter=0
L.sort()
for i in range(N-2):
    k=i+2
    for j in range(i+1,N-1):    
        while k < N and L[k] < L[i] + L[j]:
            k += 1
        counter += k - j -1
print(counter)
# Original solution
n = int(eval(input()))
nums = list(map(int,input().split(" ")))
nums.sort()
total = 0
for i in range(n):
    for j in range(i+1,n):
        k = j+1
        while k < n and nums[k] < nums[i] + nums[j]:
            k+=1    
        total += k-j -1 
print(total)

# Optimized solution
n = int(eval(input()))
nums = list(map(int,input().split(" ")))
nums.sort()
total = 0
for i in range(n-1,-1,-1):
    l = 0
    r = i-1
    while l < r:
        if nums[l] + nums[r] > nums[i]:
            total += r - l
            r -= 1
        else:
            l += 1
print(total)
# Original solution
import bisect

def main():
    N = int(eval(input()))
    L = list(map(int, input().split()))
    L = sorted(L)

    ans = 0

    for i in range(N):
        for j in range(i+1, N):
            X = L[i] + L[j]
            l = bisect.bisect_left(L, X, lo=j+1)
            ans += len(L[j+1:l])
            #print(L[j + 1:l])
    print(ans)
    return 0

if __name__ == '__main__':
    main()


# Optimized solution
import bisect

def main():
    N = int(eval(input()))
    L = list(map(int, input().split()))
    L = sorted(L)

    ans = 0

    for i in range(N):
        for j in range(i+1, N):
            X = L[i] + L[j]
            l = bisect.bisect_left(L, X, lo=j+1)
            ans += (l-(j+1))
            #print(L[j + 1:l])
    print(ans)
    return 0

if __name__ == '__main__':
    main()
# Original solution
n = int(eval(input()))
l = sorted([int(x) for x in input().split()])

ret = 0

for i in range(len(l)):
	a = l[i]
	for j in range(i + 1, len(l)):
		b = l[j]
		for k in range(j+1, len(l)):
			c = l[k]
			if c >= a+b:
				break
			if a<b+c and b<a+c and c<a+b:
				ret += 1

print(ret)

# Optimized solution
n = int(eval(input()))
a = sorted([int(x) for x in input().split()])
ret = 0
for i in range(n-1, 0, -1):
	l = 0
	r = i-1
	while l<r:
		if a[l]+a[r]>a[i]:
			ret += r - l
			r -= 1
		else:
			l += 1

print(ret)
# Original solution
# D - Triangles
n = (int)(eval(input()))
length = list(map(int, input().split()))

sum = 0

for i in range(n):
    for j in range(n):
        for k in range(n):

            a = length[i]
            b = length[j]
            c = length[k]


            if i >= j or i >= k or j >= k:
                continue

            if a < b + c and b < c + a and c < a + b:
                sum += 1

print(sum)

# Optimized solution
# D - Triangles

import bisect

n = (int)(eval(input()))
length = list(map(int, input().split()))

sum = 0

length.sort()

for i in range(n):
    for j in range(n):

            a = length[i]
            b = length[j]

            if i < j:
                k = bisect.bisect_left(length, a + b)
                sum += k - j - 1

print((max(0, sum)))
# Original solution
import bisect

N = int(eval(input()))
lst =list(map(int, input().split()))
lst.sort()
ret = 0
for i in range(N):
    for j in range(i + 1, N):
        n = lst[i] + lst[j]
        idx = bisect.bisect_left(lst, n)
        ret += max(0, idx - j - 1)
print(ret)

# Optimized solution
import bisect

N = int(eval(input()))
lst =list(map(int, input().split()))
lst.sort()
ret = 0
for i in range(N):
    for j in range(i + 1, N):
        n = lst[i] + lst[j]
        idx = bisect.bisect_left(lst, n, j + 1, N)
        ret += max(0, idx - j - 1)
print(ret)
# Original solution
import itertools

N = int(eval(input()))
L = list(map(int,input().split()))

# N = 2000
# L = list(range(N))

# # 重複を消す
# L = list(set(L))
# N = len(L)

# Lを小さい順にソート
L = sorted(L)

# j=0〜max(L)について，L[i]<jを満たす最大のi: X[j] = i
X = []
for j in range(L[-1]+1):
    flag = False
    for i in range(N-1,-1,-1):
        if L[i] < j:
            X.append(i)
            flag = True
            break
    # 見つからなければ
    if not flag: X.append(None)

# j=0〜max(L)について，L[i]>jを満たす最小のi: Y[j] = i
Y = []
for j in range(L[-1]+1):
    flag = False
    for i in range(N):
        if L[i] > j:
            Y.append(i)
            flag = True
            break
    # 見つからなければ
    if not flag: Y.append(None)

#print(L)

ind1 = 0
ind2 = N-1
ans = 0
for i in range(N-2):
    a = L[i]
    for j in range(i+1,N-1):
        b = L[j]

        # print(b-a,a+b,Y[b-a],X[a+b])

        # cのindexの範囲 = Y[b-a]〜X[a+b]
        cmin = Y[b-a]
        if a+b <= L[-1]:
            cmax = X[a+b]
        else:
            cmax = N - 1

        # cminはjより大きい
        if cmin is not None and cmin <= j:
            cmin = j + 1

        #print(b-a,a+b,cmin,cmax)

        # if a == 2 and b == 3:
        #     print(b-a,a+b,cmin,cmax)
        #     exit()
        
            
        # どちらかがNoneなら0
        if cmin is not None and cmax is not None and cmin <= cmax:
            ans += cmax - cmin + 1

print(ans)

# Optimized solution
import itertools
import bisect
            

N = int(eval(input()))
L = list(map(int,input().split()))

# Lを小さい順にソート
L = sorted(L)

# a <= b <= cを仮定してもおｋ
# a,bを全探索し，条件を満たすcの数をO(N)未満の方法で求めればよい
ans = 0
for i in range(N-2):
    a = L[i]
    for j in range(i+1,N-1):
        b = L[j]

        # Lの中で条件b-a<cを満たす最小のc
        ind_cmin = j+1

        # Lの中で条件L[k]<a+bを満たす最大のk = Lの中で昇順ソートを崩さずa+bを挿入できる最小のインデックス-1
        # 2分法で探す
        ind_cmax = bisect.bisect_left(L,a+b) - 1

        ans += ind_cmax - ind_cmin + 1

print(ans)
# Original solution
N = int(eval(input()))
L = list(map(int,input().split()))
L.sort(reverse=True)
ans = 0    
for i in range (0,N-2):
  max = sum(x >= L[i] / 2 for x in L) 
  for j in range (i+1,max):
    n = sum(x > L[i]-L[j] for x in L[j+1:N]) 
    ans = ans + n
print(ans)  

# Optimized solution
N = int(eval(input()))
L = list(map(int,input().split()))
L.sort()
ans = 0
for i in range (N-1,1,-1): 
  s = 0 
  l = i - 1
  while l > s:
    if L[s] + L[l] > L[i]:
      ans = ans + (l - s)
      l = l - 1
    else:
      s = s + 1
print(ans)
# Original solution
n = int(eval(input()))
l = list(map(int,input().split()))
a = 0
l.sort()
for i in range(n):
    for j in range(i+1,n):
        for k in range(j+1,n):
            if l[i] + l[j] > l[k]:
                a += 1
print(a)

# Optimized solution
import bisect
n = int(eval(input()))
l = list(map(int,input().split()))
l.sort()
ans = 0
for b in range(n):
  for a in range(b):
    ans += bisect.bisect_left(l,l[a]+l[b])-(b+1)
print(ans)
# Original solution
from itertools import accumulate, permutations, combinations, combinations_with_replacement, groupby, product
# import math
# import numpy as np
# from operator import xor
import sys
sys.setrecursionlimit(10 ** 5 + 10)
# input = sys.stdin.readline

def resolve():
    N=int(eval(input()))
    L=list(map(int,input().split()))

    cnt=0
    for i in combinations(L,3):
        if sum(i)-2*i[0]>0 and sum(i) - 2 * i[1] > 0 and sum(i)-2*i[2]>0:
            cnt+=1
            
    print(cnt)

resolve()

# Optimized solution
import bisect
# from collections import Counter, deque
# from copy import copy, deepcopy
# from fractions import gcd
# from functools import reduce
# from itertools import accumulate, permutations, combinations, combinations_with_replacement, groupby, product
# import math
# import numpy as np
# from operator import xor
import sys
sys.setrecursionlimit(10 ** 5 + 10)
# input = sys.stdin.readline

def resolve():
    N=int(eval(input()))
    L=sorted(list(map(int,input().split())))
    cnt=0
    for i in range(N-2):
        for j in range(i+1,N-1):

            val=bisect.bisect_left(L,L[i]+L[j])
            cnt+=val-j-1

    print(cnt)

resolve()
# Original solution
import itertools

N = int(eval(input()))

L = list(map(int,input().split()))

edge = list(itertools.combinations(L,3))

con = 0

for i in range(0,len(edge)):
	edge[i] = list(edge[i])
	edge[i].sort(reverse = True)
	a = edge[i][0]
	b = edge[i][1]
	c = edge[i][2]
	if a < b + c:
		con += 1
		
print(con)

# Optimized solution
from bisect import bisect_left

N = int(eval(input()))

L = list(map(int,input().split()))

L.sort()

con = 0

for i in range(0,N):
  for j in range(i + 1,N):
    a = L[i]
    b = L[j]
    #a + bよりでかい最小の数のインデックス
    p = bisect_left(L,a + b)
    #cとbの間の区間を取る
    con += (p - 1) - j


print(con)
# Original solution
#!/usr/bin/env python3
N = int(eval(input()))
L = sorted([int(s) for s in input().split()])

MAX_SEARCH = max(L) + 1


def check_search(middle, idx_short2, l_lng, l_lows):
    return l_lows[middle] + l_lows[idx_short2] > l_lng


l_lows = L[:2]
triangles = 0


for l_lng in L[2:]:
    for idx, l_low in enumerate(l_lows):
        left = 0
        right = len(l_lows) - 1 - idx
        end = right
        while (left < right):
            middle = (left + right) // 2
            if check_search(middle, len(l_lows) - 1 - idx, l_lng, l_lows):
                right = middle
            else:
                left = middle + 1
        triangles += (end - right)
    l_lows.append(l_lng)

print(triangles)


# Optimized solution
#!/usr/bin/env python3
N = int(eval(input()))
L = sorted([int(s) for s in input().split()])


def check_search(middle, idx_short2, l_lng, l_lows):
    return l_lows[middle] + l_lows[idx_short2] > l_lng


l_lows = L[:2]
triangles = 0


for l_lng in L[2:]:
    for idx, l_low in enumerate(l_lows):
        left = 0
        right = len(l_lows) - 1 - idx
        end = right
        while (left < right):
            middle = (left + right) // 2
            if check_search(middle, len(l_lows) - 1 - idx, l_lng, l_lows):
                right = middle
            else:
                left = middle + 1
        triangles += (end - right)
    l_lows.append(l_lng)

print(triangles)
# Original solution
import itertools

N = int(eval(input()))
l = list(map(int, input().split()))
t = list(itertools.combinations(l, 3))

count = 0
for i in t:
    i_s = sorted(i)
    a,b,c = i_s
    if b <a+c and c<a+b:
        count+=1
print(count)



# Optimized solution
import bisect
n = int(eval(input()))
l = list(map(int,input().split()))
l.sort()
ans =0
for i in range(1,n):
    for j in range(i):
        p = l[i]+ l[j]
        q = bisect.bisect_left(l,p)
        ans += q-i-1

print(ans)
# Original solution
n,m=list(map(int,input().split()))
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())
uf=UnionFind(n)
for i in range(m):
  x,y,z=list(map(int,input().split()))
  uf.union(x-1,y-1)
print((uf.group_count()))

# Optimized solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

n,k=list(map(int,input().split()))
uf=UnionFind(n)
for i in range(k):
  a,b,c=list(map(int,input().split()))
  uf.union(a-1,b-1)
print((uf.group_count()))
# Original solution
N, M = list(map(int, input().split()))

class UnionFind():

    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

uf = UnionFind(N)
for i in range(M):
    X, Y, Z = list(map(int, input().split()))
    uf.union(X-1, Y-1)
print((len(uf.roots())))


# Optimized solution
import sys
def input(): return sys.stdin.readline().strip()
def mapint(): return list(map(int, input().split()))
sys.setrecursionlimit(10**9)

N, M = mapint()

class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [-1] * n

    def find(self, x):
        if self.parents[x] < 0:
            return x
        else:
            self.parents[x] = self.find(self.parents[x])
            return self.parents[x]

    def union(self, x, y):
        x = self.find(x)
        y = self.find(y)

        if x == y:
            return

        if self.parents[x] > self.parents[y]:
            x, y = y, x

        self.parents[x] += self.parents[y]
        self.parents[y] = x

    def size(self, x):
        return -self.parents[self.find(x)]

    def same(self, x, y):
        return self.find(x) == self.find(y)

    def members(self, x):
        root = self.find(x)
        return [i for i in range(self.n) if self.find(i) == root]

    def roots(self):
        return [i for i, x in enumerate(self.parents) if x < 0]

    def group_count(self):
        return len(self.roots())

    def all_group_members(self):
        return {r: self.members(r) for r in self.roots()}

    def __str__(self):
        return '\n'.join('{}: {}'.format(r, self.members(r)) for r in self.roots())

uf = UnionFind(N)
for _ in range(M):
    x, y, z = mapint()
    uf.union(x-1, y-1)
print((uf.group_count()))
# Original solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.root = [-1]*n
        self.rank = [0]*n

    def find(self, x):
        if self.root[x-1] < 0:
            return x
        else:
            self.root[x-1] = self.find(self.root[x-1])
            return self.root[x-1]

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x==y:
            return
        elif self.rank[x-1] > self.rank[y-1]:
            self.root[x-1] += self.root[y-1]
            self.root[y-1] = x
        else:
            self.root[y-1] += self.root[x-1]
            self.root[x-1] = y
            if self.rank[x-1] == self.rank[y-1]:
                self.rank[y-1] += 1

    def same(self, x, y):
        return self.find(x)==self.find(y)

    def count(self, x):
        return -self.root[self.find(x)-1]

N,M=list(map(int,input().split()))
uf=UnionFind(N)
for i in range(M):
    x,y,z=list(map(int,input().split()))
    uf.unite(x,y)
s=set()
ans=0
for i in range(1,N+1):
    if uf.find(i) not in s:
        s.add(uf.find(i))
        ans+=1
print(ans)

# Optimized solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.root = [-1]*n
        self.rank = [0]*n

    def find(self, x):
        if self.root[x-1] < 0:
            return x
        else:
            self.root[x-1] = self.find(self.root[x-1])
            return self.root[x-1]

    def unite(self, x, y):
        x = self.find(x)
        y = self.find(y)
        if x==y:
            return
        elif self.rank[x-1] > self.rank[y-1]:
            self.root[x-1] += self.root[y-1]
            self.root[y-1] = x
            self.n-=1
        else:
            self.n-=1
            self.root[y-1] += self.root[x-1]
            self.root[x-1] = y
            if self.rank[x-1] == self.rank[y-1]:
                self.rank[y-1] += 1

    def same(self, x, y):
        return self.find(x)==self.find(y)

    def count(self, x):
        return -self.root[self.find(x)-1]
    def num(self):
        return self.n

N,M=list(map(int,input().split()))
uf=UnionFind(N)
for i in range(M):
    x,y,z=list(map(int,input().split()))
    uf.unite(x,y)
print((uf.num()))
# Original solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        self.size = [1 for _ in range(n)]

    def find(self, x):
        root = x
        while self.parents[root] != root:
            root = self.parents[root]
        while self.parents[x] != root:
            parent = self.parents[x]
            self.parents[x] = root
            x = parent
        return root

    def unite(self, x, y):
        xroot = self.find(x)
        yroot = self.find(y)
        if xroot == yroot:
            return
        xrank = self.rank[xroot]
        yrank = self.rank[yroot]
        if xrank < yrank:
            self.parents[xroot] = yroot
            self.size[yroot] += self.size[xroot]
        elif xrank == yrank:
            self.parents[yroot] = xroot
            self.rank[yroot] += 1
            self.size[xroot] += self.size[yroot]
        else:
            self.parents[yroot] = xroot
            self.size[xroot] += self.size[yroot]

    def len(self, x):
        return self.size[self.find(x)]

N, M = list(map(int, input().split()))

uf = UnionFind(N)

for _ in range(M):
    x, y, z = list(map(int, input().split()))
    uf.unite(x - 1, y - 1)

print((len(set([uf.find(i) for i in range(N)]))))

# Optimized solution
class UnionFind():
    def __init__(self, n):
        self.n = n
        self.parents = [i for i in range(n)]
        self.rank = [0 for _ in range(n)]
        self.size = [1 for _ in range(n)]

    def find(self, x):
        root = x
        while self.parents[root] != root:
            root = self.parents[root]
        while self.parents[x] != root:
            parent = self.parents[x]
            self.parents[x] = root
            x = parent
        return root

    def unite(self, x, y):
        xroot = self.find(x)
        yroot = self.find(y)
        if xroot == yroot:
            return
        xrank = self.rank[xroot]
        yrank = self.rank[yroot]
        if xrank < yrank:
            self.parents[xroot] = yroot
            self.size[yroot] += self.size[xroot]
        elif xrank == yrank:
            self.parents[yroot] = xroot
            self.rank[yroot] += 1
            self.size[xroot] += self.size[yroot]
        else:
            self.parents[yroot] = xroot
            self.size[xroot] += self.size[yroot]

    def len(self, x):
        return self.size[self.find(x)]

N, M = list(map(int, input().split()))

uf = UnionFind(N)

for _ in range(M):
    x, y, z = list(map(int, input().split()))
    uf.unite(x - 1, y - 1)

print((len([i for i in range(N) if uf.rank[i] == 0])))
# Original solution
import sys
sys.setrecursionlimit(10 ** 7)

def dfs(s):
    if visited[s]:
        return
    visited[s] = 1
    for to in t[s]:
        if visited[to]:
            continue
        dfs(to)
    
N, M = list(map(int,input().split()))
t = [[] for _ in range(N)]
visited = [0] * N
for _ in range(M):
    X, Y, Z = list(map(int,input().split()))
    X -= 1
    Y -= 1
    t[X].append(Y)
    t[Y].append(X)
ans = 0
for i in range(0, N):
    if visited[i]:
        continue
    ans += 1
    dfs(i)
print(ans)

# Optimized solution
N, M = list(map(int,input().split()))
t = [[] for _ in range(N)]
visited = [0] * N
for _ in range(M):
    X, Y, Z = list(map(int,input().split()))
    X -= 1
    Y -= 1
    t[X].append(Y)
    t[Y].append(X)
ans = 0
for i in range(N):
    if visited[i]:
        continue
    ans += 1
    stack = [i]
    while stack:
        s = stack.pop()
        for to in t[s]:
            if visited[to]:
                continue
            visited[to] = 1
            stack.append(to)
print(ans)
# Original solution
import sys
sys.setrecursionlimit(100000)

def visit_tree(now, num):
    visited[now] = num
    for i in range(len(tree[now])):
        if not visited[tree[now][i]]:
            visit_tree(tree[now][i], num)

n, m = list(map(int, input().split()))
tree = [[] for _ in range(n)]
for i in range(m):
    x, y, z = list(map(int, input().split()))
    tree[x - 1].append(y - 1)
    tree[y - 1].append(x - 1)

visited = [0 for _ in range(n)]
num = 0
for i in range(n):
    if not visited[i]:
        num += 1
        visit_tree(i, num)

print(num)

# Optimized solution
import sys
sys.setrecursionlimit(10000000)

def visit_tree(now, num):
    visited[now] = num
    for i in range(len(tree[now])):
        if not visited[tree[now][i]]:
            visit_tree(tree[now][i], num)

n, m = list(map(int, input().split()))
tree = [[] for _ in range(n)]
for i in range(m):
    x, y, z = list(map(int, input().split()))
    tree[x - 1].append(y - 1)
    tree[y - 1].append(x - 1)

visited = [0 for _ in range(n)]
num = 0
for i in range(n):
    if not visited[i]:
        num += 1
        visit_tree(i, num)

print(num)
# Original solution
N, M = list(map(int, input().split()))
nodes = [i for i in range(N)]


def root(x):
    while nodes[x] != x:
        x = nodes[x]
    return x


def same(x, y):
    return root(x) == root(y)


def unite(x, y):
    if not same(x, y):
        nodes[root(y)] = root(x)


for _ in range(M):
    X, Y, Z = list(map(int, input().split()))
    unite(X-1, Y-1)


ans = 0
for i in range(len(nodes)):
    if nodes[i] == i:
        ans += 1

print(ans)


# Optimized solution
N, M = list(map(int, input().split()))
nodes = [i for i in range(N)]


def root(x):
    if nodes[x] == x:
        return x
    else:
        nodes[x] = root(nodes[x])
    return nodes[x]


def same(x, y):
    return root(x) == root(y)


def unite(x, y):
    if not same(x, y):
        nodes[root(x)] = root(y)


for _ in range(M):
    X, Y, Z = list(map(int, input().split()))
    unite(X-1, Y-1)


ans = 0
for i in range(len(nodes)):
    if nodes[i] == i:
        ans += 1

print(ans)