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.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;

public class R170_C implements Runnable{
    
    int n;
    Map<Integer, List> g;
    List<Integer> comp;
    boolean[] used;
    
    private void dfs (int v) {
        used[v] = true;
        comp.add(v);
        for (int i=0; i < g.get(v).size(); ++i) {
            int to = (Integer) g.get(v).get(i);
            if (! used[to])
                dfs (to);
        }
    }
     
    private int find_comps() {
        int count = 0;
        for (int i=0; i<n; ++i)
            used[i] = false;
        for (int i=0; i<n; ++i) {
            if (!used[i]) {
                comp.clear();
                dfs (i);
     
//              out.print("Component:");
//              for (int j=0; j<comp.size(); ++j)
//                  out.print(" " + comp.get(j));
//              out.println();
                count++;
            }
        }
        return count;
    }
    
    private void solve() throws IOException {
        n = scanner.nextInt();
        int m = scanner.nextInt();
        Map<Integer, Set> map = new HashMap<Integer, Set>();
        // read input
        for (int i = 0; i < n; i++) {
            int k = scanner.nextInt();
            Set<Integer> set = new HashSet<Integer>();
            for (int j = 0; j < k; j++) {
                set.add(scanner.nextInt());
            }
            map.put(i, set);
        }
        
        // create a graph
        g = new HashMap<Integer, List>();
        for (int i : map.keySet()) {
            List<Integer> list = new LinkedList<Integer>();
            for (int j : map.keySet()) {
                if (i != j) {
                    Set<Integer> intersection = new HashSet<Integer>(map.get(i));
                    intersection.retainAll(map.get(j));
                    if (!intersection.isEmpty()) {
                        list.add(j);
                    }
                }
            }
            g.put(i, list);
        }
        
        comp = new LinkedList<Integer>();
        used = new boolean[n];

        // find connected components
        int res = find_comps();
        boolean allDummy = true;
        for (int i : map.keySet()) {
            if (!map.get(i).isEmpty()) {
                allDummy = false;
                break;
            }
        }
        
        res = allDummy ? res : res-1;
        out.println(res);
    }
    
    private char[] increase(char[] sequence) {
        boolean changed = false;
        for (int i = sequence.length-1; i >= 0; i--) {
            if (sequence[i] < 'z') {
                sequence[i]++;
                changed = true;
                break;
            } else if (sequence[i] == 'z') {
                sequence[i] = 'a';
            }
        }
        if (!changed) {
            char[] copy = new char[sequence.length+1];
            for (int i = 0; i < copy.length; i++) {
                copy[i] = 'a';
            }
            sequence = copy;
        }
        return sequence;
    }

    /////////////////////////////////////////////////
    final int BUF_SIZE = 1024 * 1024 * 8;//important to read long-string tokens properly
    final int INPUT_BUFFER_SIZE = 1024 * 1024 * 8 ;
    final int BUF_SIZE_INPUT = 1024;
    
    final int BUF_SIZE_OUT = 1024;
    
    boolean inputFromFile = false;
    String filenamePrefix = "A-small-attempt0";
    String inSuffix = "in.txt";
    String outSuffix = "out.txt";
    
    //InputStream bis;
    //OutputStream bos;
    PrintStream out;
    ByteScanner scanner;
    ByteWriter writer;
    
//  @Override
    public void run() {
        try{
            InputStream bis = null;
            OutputStream bos = null;
            //PrintStream out = null;
            if (inputFromFile){
                File baseFile = new File(getClass().getResource("/").getFile());
                bis = new BufferedInputStream(
                        new FileInputStream(new File(
                                baseFile, filenamePrefix+inSuffix)),
                                INPUT_BUFFER_SIZE);
                bos = new BufferedOutputStream(
                        new FileOutputStream(
                                new File(baseFile, filenamePrefix+outSuffix)));
                out = new PrintStream(bos);
            }else{
                bis = new BufferedInputStream(System.in, INPUT_BUFFER_SIZE);
                bos = new BufferedOutputStream(System.out);
                out = new PrintStream(bos);
            }
            scanner = new ByteScanner(bis, BUF_SIZE_INPUT, BUF_SIZE);
            writer = new ByteWriter(bos, BUF_SIZE_OUT);
            
            solve();
            out.flush();
        }catch (Exception e) {
            e.printStackTrace();
            System.exit(1);
        }
    }
    
    public interface Constants {
        final static byte ZERO = '0';//48 or 0x30
        final static byte NINE = '9';
        final static byte SPACEBAR = ' '; //32 or 0x20
        final static byte MINUS = '-'; //45 or 0x2d 
        
        final static char FLOAT_POINT = '.';
    }
    
    public static class EofException extends IOException{
    }
    
    public static class ByteWriter implements Constants {
        
        int bufSize = 1024;
        byte[] byteBuf = new byte[bufSize];
        OutputStream os;
        
        public ByteWriter(OutputStream os, int bufSize){
            this.os = os;
            this.bufSize = bufSize;
        }
        
        public void writeInt(int num) throws IOException{
             int byteWriteOffset = byteBuf.length;
             if (num==0){
                 byteBuf[--byteWriteOffset] = ZERO;
             }else{
                 int numAbs = Math.abs(num);
                 while (numAbs>0){
                     byteBuf[--byteWriteOffset] = (byte)((numAbs % 10) + ZERO);
                     numAbs /= 10;
                 }
                 if (num<0)
                     byteBuf[--byteWriteOffset] = MINUS;
             }
             os.write(byteBuf, byteWriteOffset, byteBuf.length - byteWriteOffset);
        }
        
        /**
         * Please ensure ar.length <= byteBuf.length!
         * 
         * @param ar
         * @throws IOException
         */
        public void writeByteAr(byte[] ar) throws IOException{
            for (int i = 0; i < ar.length; i++) {
                byteBuf[i] = ar[i];
            }
            os.write(byteBuf,0,ar.length);
        }
        
        public void writeSpaceBar() throws IOException{
            byteBuf[0] = SPACEBAR;
            os.write(byteBuf,0,1);
        }
        
    }
    
    public static class ByteScanner implements Constants{
        
        InputStream is;
        
        public ByteScanner(InputStream is, int bufSizeInput, int bufSize){
            this.is = is;
            this.bufSizeInput = bufSizeInput;
            this.bufSize = bufSize;
            
            byteBufInput = new byte[this.bufSizeInput];
            byteBuf = new byte[this.bufSize];
        }
        
        public ByteScanner(byte[] data){
            byteBufInput = data;
            bufSizeInput = data.length;
            bufSize = data.length;
            byteBuf = new byte[bufSize];
            byteRead = data.length;
            bytePos = 0;
        }
        
        private int bufSizeInput;
        private int bufSize;
        
        byte[] byteBufInput;
        byte by=-1;
        int byteRead=-1;
        int bytePos=-1;

        byte[] byteBuf;
        int totalBytes;
        
        boolean eofMet = false;
        
        private byte nextByte() throws IOException{
            
            if (bytePos<0 || bytePos>=byteRead){
                byteRead = is==null? -1: is.read(byteBufInput);
                bytePos=0;
                if (byteRead<0){
                    byteBufInput[bytePos]=-1;//!!!
                    if (eofMet)
                        throw new EofException();
                    eofMet = true;
                }
            }
            return byteBufInput[bytePos++];
        }
        
        /**
         * Returns next meaningful character as a byte.<br>
         * 
         * @return
         * @throws IOException
         */
        public byte nextChar() throws IOException{
            while ((by=nextByte())<=0x20);
            return by;
        }
        
        /**
         * Returns next meaningful character OR space as a byte.<br>
         * 
         * @return
         * @throws IOException
         */
        public byte nextCharOrSpacebar() throws IOException{
            while ((by=nextByte())<0x20);
            return by;
        }
        
        /**
         * Reads line.
         * 
         * @return
         * @throws IOException
         */
        public String nextLine() throws IOException {
            readToken((byte)0x20);
            return new String(byteBuf,0,totalBytes);
        }
        
        public byte[] nextLineAsArray() throws IOException {
            readToken((byte)0x20);
            byte[] out = new byte[totalBytes];
            System.arraycopy(byteBuf, 0, out, 0, totalBytes);
            return out;
        }
        
        
        /**
         * Reads token. Spacebar is separator char.
         * 
         * @return
         * @throws IOException
         */
        public String nextToken() throws IOException {
            readToken((byte)0x21);
            return new String(byteBuf,0,totalBytes);
        }
        
        /**
         * Spacebar is included as separator char
         * 
         * @throws IOException
         */
        private void readToken() throws IOException {           
            readToken((byte)0x21);
        }
        
        private void readToken(byte acceptFrom) throws IOException {
            totalBytes = 0;
            while ((by=nextByte())<acceptFrom);
            byteBuf[totalBytes++] = by;
            while ((by=nextByte())>=acceptFrom){
                byteBuf[totalBytes++] = by;
            }
        }
        
        public int nextInt() throws IOException{
            readToken();
            int num=0, i=0;
            boolean sign=false;
            if (byteBuf[i]==MINUS){
                sign = true;
                i++;
            }
            for (; i<totalBytes; i++){
                num*=10;
                num+=byteBuf[i]-ZERO;
            }
            return sign?-num:num;
        }
        
        public long nextLong() throws IOException{
            readToken();
            long num=0;
            int i=0;
            boolean sign=false;
            if (byteBuf[i]==MINUS){
                sign = true;
                i++;
            }
            for (; i<totalBytes; i++){
                num*=10;
                num+=byteBuf[i]-ZERO;
            }
            return sign?-num:num;
        }
        
        /*
        //TODO test Unix/Windows formats
        public void toNextLine() throws IOException{
            while ((ch=nextChar())!='\n');
        }
        */
        
        public double nextDouble() throws IOException{
            readToken();
            char[] token = new char[totalBytes];
            for (int i = 0; i < totalBytes; i++) {
                token[i] = (char)byteBuf[i];
            }
            return Double.parseDouble(new String(token));
        }
        
        public int[] loadIntArray(int size) throws IOException{
            int[] a = new int[size];
            for (int i = 0; i < a.length; i++) {
                a[i] = nextInt();
            }
            return a;
        }
        
        public long[] loadLongArray(int size) throws IOException{
            long[] a = new long[size];
            for (int i = 0; i < a.length; i++) {
                a[i] = nextLong();
            }
            return a;
        }
        
    }
    
    
    public static abstract class Timing{
        private static int counter = 0;
        protected String name = "Timing"+(++counter);
        private boolean debug;
        
        public Timing(boolean debug) {
            super();
            this.debug = debug;
        }
        
        public abstract void run();
        public void start(){
            long time1 = System.currentTimeMillis();
            run();
            long time2 = System.currentTimeMillis();
            if (debug)
                System.out.println(name+" time = "+(time2-time1)/1000.0+" ms.");
        }
        
    }
    
    public static class Alg{
        public static interface BooleanChecker{
            public boolean check(long arg);
        }
        
        public static class BinarySearch{
                    
            /**
             * This check returns boolean value, result of function.
             * It should be monotonic.
             * 
             * @return
             */
            public BooleanChecker bc;
            
            
            /**
             * Returns following element: <pre> 0 0 [1] 1 1</pre>
             */
            public long search(long left, long right){
                while (left<=right){
                    long mid = (left+right)/2;
                    if (bc.check(mid)){
                        right = mid-1;
                    }else{
                        left = mid+1;
                    }
                }
                return left;
            }
            
            /**
             * Optional.<br>
             * Returns following element: <pre> 1 1 [1] 0 0</pre>
             */
            public long searchInverted(long left, long right){
                while (left<=right){
                    long mid = (left+right)/2;
                    if (!bc.check(mid)){
                        right = mid-1;
                    }else{
                        left = mid+1;
                    }
                }
                return left - 1; 
            }
        }
    }
    
    public static class Modulo{
        long mod = (long)1e9+7;
        
        public Modulo(long mod) {
            super();
            this.mod = mod;
        }

        public long inv(long a) {
            long res =  pow(a, mod-2);
            return res;
        }

        public long pow(long a, long x) {
            if (x==0)
                return 1;
            long part = 1;
            if ((x&1)!=0)
                part = a;
            return (part * pow((a*a)%mod, x>>1)) % mod;
        }
        
    }
    
    public static void main(String[] args) {
        new R170_C().run();
    }
    
}