The "BerCorp" company has got n employees. These employees can use m approved official languages for the formal correspondence. The languages are numbered with integers from 1 to m. For each employee we have the list of languages, which he knows. This list could be empty, i. e. an employee may know no official languages. But the employees are willing to learn any number of official languages, as long as the company pays their lessons. A study course in one language for one employee costs 1 berdollar.

Find the minimum sum of money the company needs to spend so as any employee could correspond to any other one (their correspondence can be indirect, i. e. other employees can help out translating).

Input

The first line contains two integers n and m (2 ≤ n, m ≤ 100) — the number of employees and the number of languages.

Then n lines follow — each employee's language list. At the beginning of the i-th line is integer ki (0 ≤ ki ≤ m) — the number of languages the i-th employee knows. Next, the i-th line contains ki integers — aij (1 ≤ aij ≤ m) — the identifiers of languages the i-th employee knows. It is guaranteed that all the identifiers in one list are distinct. Note that an employee may know zero languages.

The numbers in the lines are separated by single spaces.

Output

Print a single integer — the minimum amount of money to pay so that in the end every employee could write a letter to every other one (other employees can help out translating).

Examples

Input

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


Output

0


Input

8 7
0
3 1 2 3
1 1
2 5 4
2 6 7
1 3
2 7 4
1 1


Output

2


Input

2 2
1 2
0


Output

1

Note

In the second sample the employee 1 can learn language 2, and employee 8 can learn language 4.

In the third sample employee 2 must learn language 2.
import static java.lang.Math.*;
import static java.math.BigInteger.*;
import static java.util.Arrays.*;

import java.io.*;
import java.lang.reflect.*;
import java.util.*;

public class A {

	final int MOD = (int)1e9 + 7;
	final double eps = 1e-12;
	final int INF = (int)1e3;
	
	public A () {
		int N = sc.nextInt();
		int M = sc.nextInt();
		
		boolean [] L = new boolean [M];
		int X = 0;
		
		Integer [][] P = new Integer [N][];
		for (int i : rep(N)) {
			int K = sc.nextInt();
			if (K == 0)
				++X;
			P[i] = sc.nextInt(K);
			for (int j : rep(K))
				L[--P[i][j]] = true;
		}

		Set<Integer> SE = new TreeSet<Integer>();
		for (int i : rep(N))
			for (int j : rep(P[i].length))
				for (int k : rep(j+1, P[i].length)) {
					int x = min(P[i][j], P[i][k]), y = max(P[i][j], P[i][k]);
					SE.add(INF * x + y);
			}
		
		int Z = SE.size();
		int [][] E = new int [Z][]; int e = 0;
		for (int z : SE)
			E[e++] = new int [] { z/INF, z%INF };

		
		int [] C = cc(E, M); int Y = -1;
		for (int i : rep(M))
			if (L[i] && C[i] == i)
				++Y;

		int res = X + max(Y, 0);
		exit(res);
	}

	int [] cc (int [][] E, int N) { /* int [][2] E */
		int [] C = new int [N];
		for (int i : rep(N))
			C[i] = i;
		
		for (int k : rep(E.length))
			C[root(C,E[k][0])] = C[root(C,E[k][1])];
		
		for (int i : rep(N))
			root(C,i);
		
		return C;
	}

	int root(int [] C, int s) {
		int r = s;
		while (C[r] != r)
			r = C[r];
		int v = s;
		while (v != r) {
			v = C[v];
			C[v] = r;
		}
		return C[s] = r;
	}
	
	////////////////////////////////////////////////////////////////////////////////////

	static int [] rep(int N) { return rep(0, N); }
	static int [] rep(int S, int T) { int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	static int [] req(int S, int T) { return rep(S, T+1); }	

	////////////////////////////////////////////////////////////////////////////////////

	/* Dear hacker, don't bother reading below this line, unless you want to help me debug my I/O routines :-) */
	
	static MyScanner sc = new MyScanner();
	
	static class MyScanner {
		public String next() {
			newLine();
			return line[index++];
		}
		
		public char nextChar() {
			return next().charAt(0);
		}
				
		public int nextInt() {
			return Integer.parseInt(next());
		}
		
		public long nextLong() {
			return Long.parseLong(next());
		}
		
		public double nextDouble() {
			return Double.parseDouble(next());
		}
		
		public String nextLine() {
			line = null;
			return readLine();
		}
		
		public String [] nextStrings() {
			line = null;
			return readLine().split(" ");
		}
		
		public char [] nextChars() {
			return next().toCharArray();
		}

		public Integer [] nextInts() {
			String [] L = nextStrings();
			Integer [] res = new Integer [L.length];
			for (int i = 0; i < L.length; ++i)
				res[i] = Integer.parseInt(L[i]);
			return res;
		}	
		
		public Long [] nextLongs() {
			String [] L = nextStrings();
			Long [] res = new Long [L.length];
			for (int i = 0; i < L.length; ++i)
				res[i] = Long.parseLong(L[i]);
			return res;
		}

		public Double [] nextDoubles() {
			String [] L = nextStrings();
			Double [] res = new Double [L.length];
			for (int i = 0; i < L.length; ++i)
				res[i] = Double.parseDouble(L[i]);
			return res;
		}

		public String [] next (int N) {
			String [] res = new String [N];
			for (int i = 0; i < N; ++i)
				res[i] = sc.next();
			return res;
		}
		
		public Integer [] nextInt (int N) {
			Integer [] res = new Integer [N];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextInt();
			return res;
		}		
		
		public Long [] nextLong (int N) {
			Long [] res = new Long [N];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextLong();
			return res;
		}		
		
		public Double [] nextDouble (int N) {
			Double [] res = new Double [N];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextDouble();
			return res;
		}		
		
		public String [][] nextStrings (int N) {
			String [][] res = new String [N][];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextStrings();
			return res;
		}
		
		public Integer [][] nextInts (int N) {
			Integer [][] res = new Integer [N][];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextInts();
			return res;
		}
		
		public Long [][] nextLongs (int N) {
			Long [][] res = new Long [N][];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextLongs();
			return res;
		}
		
		public Double [][] nextDoubles (int N) {
			Double [][] res = new Double [N][];
			for (int i = 0; i < N; ++i)
				res[i] = sc.nextDoubles();
			return res;
		}
		
		//////////////////////////////////////////////
		
		private boolean eol() {
			return index == line.length;
		}

		private String readLine() {
			try {
				return r.readLine();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		private final BufferedReader r;

		MyScanner () {
			this(new BufferedReader(new InputStreamReader(System.in)));
		}
		
		MyScanner(BufferedReader r) {
			try {
				this.r = r;
				while (!r.ready())
					Thread.sleep(1);
				start();
			} catch (Exception e) {
				throw new Error(e);
			}
		}
		
		private String [] line;
		private int index;

		private void newLine() {
			if (line == null || eol()) {
				line = readLine().split(" ");
				index = 0;
			}
		}		
	}
	
	static void print(Object o, Object... a) {
		printDelim(" ", o, a);
	}
	
	static void cprint(Object o, Object... a) {
		printDelim("", o, a);
	}
	
	static void printDelim (String delim, Object o, Object... a) {
		pw.println(build(delim, o, a));
	}

	static void exit (Object o, Object... a) {
		print(o, a);
		exit();
	}

	static void exit () {
		pw.close();
		System.out.flush();
		System.err.println("------------------");
		System.err.println("Time: " + ((millis() - t) / 1000.0));
		System.exit(0);
	}
	
	void NO() {
		throw new Error("NO!");
	}
	
	////////////////////////////////////////////////////////////////////////////////////
	
	static String build(String delim, Object o, Object... a) {
		StringBuilder b = new StringBuilder();
		append(b, o, delim);
		for (Object p : a)
			append(b, p, delim);
		return b.toString().trim();		
	}
	
	static void append(StringBuilder b, Object o, String delim) {
		if (o.getClass().isArray()) {
			int L = Array.getLength(o);
			for (int i = 0; i < L; ++i)
				append(b, Array.get(o, i), delim);
		} else if (o instanceof Iterable<?>) {
			for (Object p : (Iterable<?>)o)
				append(b, p, delim);
		} else
			b.append(delim).append(o);		
	}
	
	////////////////////////////////////////////////////////////////////////////////////
	
	static void statics() {
		abs(0);
		valueOf(0);
		sort((int[])null);
	}
	
	public static void main(String[] args) {
		new A();
		exit();
	}

	static void start() {
		t = millis();
	}

	static PrintWriter pw = new PrintWriter(System.out);
	
	static long t;
	
	static long millis() {
		return System.currentTimeMillis();
	}	
}