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 java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.io.BufferedOutputStream;
import java.util.StringTokenizer;
import java.io.BufferedReader;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 *
 * @author Aeroui
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        Kattio in = new Kattio(inputStream);
        PrintWriter out = new PrintWriter(outputStream);
        TaskA solver = new TaskA();
        solver.solve(1, in, out);
        out.close();
    }

    static class TaskA {
        public void solve(int testNumber, Kattio in, PrintWriter out) {
            int n = in.nextInt();
            int m = in.nextInt();

            ArrayList<Integer>[] employees = new ArrayList[m + 1];
            for (int i = 0; i <= m; ++i)
                employees[i] = new ArrayList<>();

            boolean flag = false;
            for (int i = 0; i < n; ++i) {
                int l = in.nextInt();
                if (l >= 1)
                    flag = true;
                for (int j = 0; j < l; ++j) {
                    employees[in.nextInt()].add(i);
                }
            }

            UnionFind UF = new UnionFind(n);
            for (int i = 1; i <= m; ++i) {
                for (int j = 1; j < employees[i].size(); ++j) {
                    UF.unionSet(employees[i].get(j), employees[i].get(j - 1));
                }
            }

            if (!flag)
                out.println(UF.numDisjointSets());
            else
                out.println(UF.numDisjointSets() - 1);
        }

        private class UnionFind {
            private ArrayList<Integer> p;
            private ArrayList<Integer> rank;
            private ArrayList<Integer> setSize;
            private int numSets;

            public UnionFind(int N) {
                p = new ArrayList<Integer>(N);
                rank = new ArrayList<Integer>(N);
                setSize = new ArrayList<Integer>(N);
                numSets = N;
                for (int i = 0; i < N; i++) {
                    p.add(i);
                    rank.add(0);
                    setSize.add(1);
                }
            }

            public int findSet(int i) {
                if (p.get(i) == i)
                    return i;
                else {
                    int ret = findSet(p.get(i));
                    p.set(i, ret);
                    return ret;
                }
            }

            public Boolean isSameSet(int i, int j) {
                return findSet(i) == findSet(j);
            }

            public void unionSet(int i, int j) {
                if (!isSameSet(i, j)) {
                    numSets--;
                    int x = findSet(i), y = findSet(j);
                    // rank is used to keep the tree short
                    if (rank.get(x) > rank.get(y)) {
                        p.set(y, x);
                        setSize.set(x, setSize.get(x) + setSize.get(y));
                    } else {
                        p.set(x, y);
                        setSize.set(y, setSize.get(y) + setSize.get(x));
                        if (rank.get(x) == rank.get(y))
                            rank.set(y, rank.get(y) + 1);
                    }
                }
            }

            public int numDisjointSets() {
                return numSets;
            }

        }

    }

    static class Kattio extends PrintWriter {
        private BufferedReader r;
        private String line;
        private StringTokenizer st;
        private String token;

        public Kattio(InputStream i) {
            super(new BufferedOutputStream(System.out));
            r = new BufferedReader(new InputStreamReader(i));
        }

        public Kattio(InputStream i, OutputStream o) {
            super(new BufferedOutputStream(o));
            r = new BufferedReader(new InputStreamReader(i));
        }

        public int nextInt() {
            return Integer.parseInt(nextToken());
        }

        private String peekToken() {
            if (token == null)
                try {
                    while (st == null || !st.hasMoreTokens()) {
                        line = r.readLine();
                        if (line == null) return null;
                        st = new StringTokenizer(line);
                    }
                    token = st.nextToken();
                } catch (IOException e) {
                }
            return token;
        }

        private String nextToken() {
            String ans = peekToken();
            token = null;
            return ans;
        }

    }
}

