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.util.*;

/**
 * 假设一共有m种语言，标记为1-m
 * 有n个人，每个人会其中的若干种语言，可能会很多种，也可能一种也不会
 * 如果两个人会同一种语言，则称他们可以交流
 * 如果两个人之间可以通过第三个人进行交流，这两个人也认为可以交流
 * 现在可以对他们进行培训，让他们中的一些人学某种语言，从而所有人之间都可以交流
 * 问需要参与培训的人数最少为多少
 *
 *
 * 思路：并查集，初始状态时把可以交流的人合并起来形成一个个小集合，就可以知道培训所需人数
 * 合并的时候代表结点可以“学会”集合内所有语言
 */
public class Main {

    public static class Element<V>{
        V value;
        public Element(V value){
            this.value=value;
        }
    }

    public static class UnionSet<V>{
        HashMap<V,Element<V>> elementMap;
        HashMap<Element<V>,Element<V>> fatherMap;
        HashMap<Element<V>, HashSet<Integer>> rankMap;
        HashMap<Element<V>,Integer> sizeMap;

        public UnionSet(List<V> values, List<List<Integer>> langs){
            elementMap=new HashMap<>();
            fatherMap=new HashMap<>();
            rankMap=new HashMap<>();
            sizeMap=new HashMap<>();
            for (V value: values) {
                Element<V> element = new Element<>(value);
                elementMap.put(value,element);
                fatherMap.put(element,element);
                sizeMap.put(element,1);
            }
            for (int i = 0; i < langs.size(); i++) {
                List<Integer> lang = langs.get(i);
                HashSet<Integer> langSet = new HashSet<>();
                for (int j = 0; j < lang.size(); j++) {
                    langSet.add(lang.get(j));
                }
                rankMap.put(elementMap.get(values.get(i)),langSet);
            }
        }

        private Element<V> findHead(Element<V> e){
            Stack<Element<V>> stack = new Stack<>();
            while (e!=fatherMap.get(e)){
                stack.push(e);
                e=fatherMap.get(e);
            }
            // 此时e是头部
            // 让回溯头部时经过的结点都直接指向头部
            while (!stack.empty()){
                fatherMap.put(stack.pop(),e);
            }
            return e;
        }

        public boolean isSameSet(V v1, V v2){
            if (elementMap.containsKey(v1) && elementMap.containsKey(v2)){
                return findHead(elementMap.get(v1))==findHead(elementMap.get(v2));
            }
            return false;
        }

        public void union(V v1, V v2){
            if (elementMap.containsKey(v1) && elementMap.containsKey(v2)){
                Element<V> father1 = findHead(elementMap.get(v1));
                Element<V> father2 = findHead(elementMap.get(v2));

                if (father1!=father2){
                    Element<V> big=sizeMap.get(father1)>sizeMap.get(father2)?father1:father2;
                    Element<V> small=big==father1?father2:father1;

                    sizeMap.put(big,sizeMap.get(small)+sizeMap.get(big));
                    sizeMap.remove(small);

                    fatherMap.put(small,big);
                    HashSet<Integer> bigRank = rankMap.get(big);
                    for (Integer i: rankMap.get(small))
                        bigRank.add(i);
                    rankMap.remove(small);
                }
            }
        }
    }

    public static boolean cantalk(HashSet<Integer> a, HashSet<Integer> b){
        Iterator<Integer> iterA = a.iterator();
        while (iterA.hasNext()){
            if (b.contains(iterA.next()))
                return true;
        }
        return false;
    }

    public static void main(String[] args) {

        Scanner scanner = new Scanner(System.in);
        while (scanner.hasNext()){
            int n=scanner.nextInt(),
                    m=scanner.nextInt();
            List<Integer> personId=new ArrayList<>();
            List<List<Integer>> langId=new ArrayList<>();

            int emptyCnt=0;

            for (int i = 0; i < n; i++) {
                personId.add(i);
                List<Integer> lang = new ArrayList<>();
                int k=scanner.nextInt();
                if (k==0)
                    emptyCnt++;
                for (int j = 0; j < k; j++) {
                    lang.add(scanner.nextInt());
                }
                langId.add(lang);
            }

            UnionSet<Integer> unionSet = new UnionSet<>(personId, langId);

            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    Element<Integer> elementi = unionSet.elementMap.get(i);
                    Element<Integer> elementj = unionSet.elementMap.get(j);
                    Element<Integer> headi = unionSet.findHead(elementi);
                    Element<Integer> headj = unionSet.findHead(elementj);
                    if (headi!=headj && cantalk(unionSet.rankMap.get(headi),unionSet.rankMap.get(headj)))
                        unionSet.union(i,j);
                }
            }

            int res=0;
            if (emptyCnt<n)
                res=unionSet.sizeMap.size()-1;
            else
                res=n;
            System.out.println(res);
        }
    }
}
     		 	  	  	  	  		 								