import java.io.OutputStreamWriter;
import java.io.BufferedWriter;
import java.util.Comparator;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.AbstractList;
import java.io.Writer;
import java.util.Collection;
import java.util.List;
import java.io.IOException;
import java.util.InputMismatchException;
import java.util.ArrayList;
import java.math.BigInteger;
import java.io.InputStream;

/**
 * Built using CHelper plug-in
 * Actual solution is at the top
 * @author Nguyen Trung Hieu - vuondenthanhcong11@yahoo.com
 */
public class Main {
    public static void main(String[] args) {
        InputStream inputStream = System.in;
        OutputStream outputStream = System.out;
        InputReader in = new InputReader(inputStream);
        OutputWriter out = new OutputWriter(outputStream);
        TaskC1 solver = new TaskC1();
        solver.solve(1, in, out);
        out.close();
    }
}

class TaskC1 {
    public void solve(int testNumber, InputReader in, OutputWriter out) {
        int count = in.readInt();
        int friendshipsCount = in.readInt();
        IndependentSetSystem setSystem = new RecursiveIndependentSetSystem(count);
        for (int i = 0; i < friendshipsCount; i++) {
            int first = in.readInt() - 1;
            int second = in.readInt() - 1;
            setSystem.join(first, second);
        }

        int[] result = new int[count];
        for (int i = 0; i < count; i++)
            result[setSystem.get(i)]++;
        int enemiesCount = in.readInt();
        for (int i = 0; i < enemiesCount; i++) {
            int first = in.readInt() - 1;
            int second = in.readInt() - 1;
            if (setSystem.get(first) == setSystem.get(second))
                result[setSystem.get(first)] = 0;
        }

        out.printLine(CollectionUtils.maxElement(Array.wrap(result)));
    }
}

class InputReader {
    private InputStream stream;
    private byte[] buf = new byte[1024];
    private int curChar;
    private int numChars;
    private SpaceCharFilter filter;

    public InputReader(InputStream stream) {
        this.stream = stream;
    }

    public int read() {
        if (numChars == -1)
            throw new InputMismatchException();
        if (curChar >= numChars) {
            curChar = 0;
            try {
                numChars = stream.read(buf);
            } catch (IOException e) {
                throw new InputMismatchException();
            }
            if (numChars <= 0)
                return -1;
        }
        return buf[curChar++];
    }

    public int readInt() {
        int c = read();
        while (isSpaceChar(c))
            c = read();
        int sgn = 1;
        if (c == '-') {
            sgn = -1;
            c = read();
        }
        int res = 0;
        do {
            if (c < '0' || c > '9')
                throw new InputMismatchException();
            res *= 10;
            res += c - '0';
            c = read();
        } while (!isSpaceChar(c));
        return res * sgn;
    }

    public boolean isSpaceChar(int c) {
        if (filter != null)
            return filter.isSpaceChar(c);
        return c == ' ' || c == '\n' || c == '\r' || c == '\t' || c == -1;
    }

    public interface SpaceCharFilter {
        public boolean isSpaceChar(int ch);
    }

    }

class OutputWriter {
    private final PrintWriter writer;

    public OutputWriter(OutputStream outputStream) {
        writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream)));
    }

    public OutputWriter(Writer writer) {
        this.writer = new PrintWriter(writer);
    }

    public void print(Object...objects) {
        for (int i = 0; i < objects.length; i++) {
            if (i != 0)
                writer.print(' ');
            writer.print(objects[i]);
        }
    }

    public void printLine(Object...objects) {
        print(objects);
        writer.println();
    }

    public void close() {
        writer.close();
    }

}

interface IndependentSetSystem {
    public boolean join(int first, int second);

    int get(int index);

    public static interface Listener {
        public void joined(int joinedRoot, int root);
    }
}

class RecursiveIndependentSetSystem implements IndependentSetSystem {
    private final int[] color;
    private int setCount;
    private Listener listener;

    public RecursiveIndependentSetSystem(int size) {
        color = new int[size];
        for (int i = 0; i < size; i++)
            color[i] = i;
        setCount = size;
    }

    public RecursiveIndependentSetSystem(RecursiveIndependentSetSystem other) {
        color = other.color.clone();
        setCount = other.setCount;
    }

    public boolean join(int first, int second) {
        first = get(first);
        second = get(second);
        if (first == second)
            return false;
        setCount--;
        color[second] = first;
        if (listener != null)
            listener.joined(second, first);
        return true;
    }

    public int get(int index) {
        if (color[index] == index)
            return index;
        return color[index] = get(color[index]);
    }

    }

class CollectionUtils {

    public static<T extends Comparable<T>> T maxElement(Iterable<T> collection) {
        T result = null;
        for (T element : collection) {
            if (result == null || result.compareTo(element) < 0)
                result = element;
        }
        return result;
    }

    }

abstract class Array<T> extends AbstractList<T> {

    public static List<Integer> wrap(int...array) {
        return new IntArray(array);
    }

    protected static class IntArray extends Array<Integer> {
        protected final int[] array;

        protected IntArray(int[] array) {
            this.array = array;
        }

        public int size() {
            return array.length;
        }

        public Integer get(int index) {
            return array[index];
        }

        public Integer set(int index, Integer value) {
            int result = array[index];
            array[index] = value;
            return result;
        }
    }

    }


import java.util.Scanner;

/**
 * @Author Mikhail Linkov
 * Date: 21.04.12
 */
public class ProblemC {
    private static int [][] matrix;
    private static int [] comp;
    private static int count = 0;
    private static int compNum;
    private static int flag;

    private static void dfs(int vertex) {
        count++;
        comp[vertex] = compNum;

        for (int i = 0; i < comp.length; i++) {
            if (matrix[vertex][i] == 1) {
                if (comp[i] == -1) {
                    dfs(i);
                }
            }
            if (matrix[vertex][i] == 2) {
                if (comp[i] == comp[vertex]) {
                    flag = 1;
                }
            }
        }
    }

    public static void main(String [] args) {
        Scanner scanner = new Scanner(System.in);

        int vertexCount = scanner.nextInt();

        int friendPairsCount = scanner.nextInt();

        matrix = new int[vertexCount][vertexCount];
        comp = new int[vertexCount];
        compNum = 0;

        for (int i = 0; i < vertexCount; i++) {
            comp[i] = -1;
        }

        for (int i = 0; i < friendPairsCount; i++) {
            int a = scanner.nextInt() - 1;
            int b = scanner.nextInt() - 1;

            matrix[a][b] = 1;
            matrix[b][a] = 1;
        }

        int unFriendPairsCount = scanner.nextInt();

        for (int i = 0; i < unFriendPairsCount; i++) {
            int a = scanner.nextInt() - 1;
            int b = scanner.nextInt() - 1;

            matrix[a][b] = 2;
            matrix[b][a] = 2;
        }

        int answer = 0;

        for (int i = 0; i < vertexCount; i++) {
            if (comp[i] == -1) {
                compNum++;
                flag = 0;
                count = 0;
                dfs(i);
                if (flag == 0) {
                    if (answer < count) {
                        answer = count;
                    }
                }
            }
        }

        System.out.println(answer);
    }
}


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.StringTokenizer;

public class CodeI
{
	static class Scanner
	{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer("");

		public String nextLine()
		{
			try
			{
				return br.readLine();
			}
			catch(Exception e)
			{
				throw(new RuntimeException());
			}
		}

		public String next()
		{
			while(!st.hasMoreTokens())
			{
				String l = nextLine();
				if(l == null)
					return null;
				st = new StringTokenizer(l);
			}
			return st.nextToken();
		}

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

		public long nextLong()
		{
			return Long.parseLong(next());
		}

		public double nextDouble()
		{
			return Double.parseDouble(next());
		}

		public int[] nextIntArray(int n)
		{
			int[] res = new int[n];
			for(int i = 0; i < res.length; i++)
				res[i] = nextInt();
			return res;
		}

		public long[] nextLongArray(int n)
		{
			long[] res = new long[n];
			for(int i = 0; i < res.length; i++)
				res[i] = nextLong();
			return res;
		}

		public double[] nextDoubleArray(int n)
		{
			double[] res = new double[n];
			for(int i = 0; i < res.length; i++)
				res[i] = nextDouble();
			return res;
		}
		public void sortIntArray(int[] array)
		{
			Integer[] vals = new Integer[array.length];
			for(int i = 0; i < array.length; i++)
				vals[i] = array[i];
			Arrays.sort(vals);
			for(int i = 0; i < array.length; i++)
				array[i] = vals[i];
		}

		public void sortLongArray(long[] array)
		{
			Long[] vals = new Long[array.length];
			for(int i = 0; i < array.length; i++)
				vals[i] = array[i];
			Arrays.sort(vals);
			for(int i = 0; i < array.length; i++)
				array[i] = vals[i];
		}

		public void sortDoubleArray(double[] array)
		{
			Double[] vals = new Double[array.length];
			for(int i = 0; i < array.length; i++)
				vals[i] = array[i];
			Arrays.sort(vals);
			for(int i = 0; i < array.length; i++)
				array[i] = vals[i];
		}

		public String[] nextStringArray(int n)
		{
			String[] vals = new String[n];
			for(int i = 0; i < n; i++)
				vals[i] = next();
			return vals;
		}

		public Integer nextInteger()
		{
			String s = next();
			if(s == null)
				return null;
			return Integer.parseInt(s);
		}

		public int[][] nextIntMatrix(int n, int m)
		{
			int[][] ans = new int[n][];
			for(int i = 0; i < n; i++)
				ans[i] = nextIntArray(m);
			return ans;
		}

		public char[][] nextGrid(int r, int c)
		{
			char[][] grid = new char[r][];
			for(int i = 0; i < r; i++)
				grid[i] = next().toCharArray();
			return grid;
		}

		public static <T> T fill(T arreglo, int val)
		{
			if(arreglo instanceof Object[])
			{
				Object[] a = (Object[]) arreglo;
				for(Object x : a)
					fill(x, val);
			}
			else if(arreglo instanceof int[])
				Arrays.fill((int[]) arreglo, val);
			else if(arreglo instanceof double[])
				Arrays.fill((double[]) arreglo, val);
			else if(arreglo instanceof long[])
				Arrays.fill((long[]) arreglo, val);
			return arreglo;
		}

		<T> T[] nextObjectArray(Class <T> clazz, int size)
		{
			@SuppressWarnings("unchecked")
			T[] result = (T[]) java.lang.reflect.Array.newInstance(clazz, size);
			for(int c = 0; c < 3; c++)
			{
				Constructor <T> constructor;
				try
				{
					if(c == 0)
						constructor = clazz.getDeclaredConstructor(Scanner.class, Integer.TYPE);
					else if(c == 1)
						constructor = clazz.getDeclaredConstructor(Scanner.class);
					else
						constructor = clazz.getDeclaredConstructor();
				}
				catch(Exception e)
				{
					continue;
				}
				try
				{
					for(int i = 0; i < result.length; i++)
					{
						if(c == 0)
							result[i] = constructor.newInstance(this, i);
						else if(c == 1)
							result[i] = constructor.newInstance(this);
						else
							result[i] = constructor.newInstance();
					}
				}
				catch(Exception e)
				{
					throw new RuntimeException(e);
				}
				return result;
			}
			throw new RuntimeException("Constructor not found");
		}

		public void printLine(int... vals)
		{
			if(vals.length == 0)
				System.out.println();
			else
			{
				System.out.print(vals[0]);
				for(int i = 1; i < vals.length; i++)
					System.out.print(" ".concat(String.valueOf(vals[i])));
				System.out.println();
			}
		}

		public void printLine(long... vals)
		{
			if(vals.length == 0)
				System.out.println();
			else
			{
				System.out.print(vals[0]);
				for(int i = 1; i < vals.length; i++)
					System.out.print(" ".concat(String.valueOf(vals[i])));
				System.out.println();
			}
		}

		public void printLine(double... vals)
		{
			if(vals.length == 0)
				System.out.println();
			else
			{
				System.out.print(vals[0]);
				for(int i = 1; i < vals.length; i++)
					System.out.print(" ".concat(String.valueOf(vals[i])));
				System.out.println();
			}
		}

		public void printLine(int prec, double... vals)
		{
			if(vals.length == 0)
				System.out.println();
			else
			{
				System.out.printf("%." + prec + "f", vals[0]);
				for(int i = 1; i < vals.length; i++)
					System.out.printf(" %." + prec + "f", vals[i]);
				System.out.println();
			}
		}
	}

	static class Person
	{
		int id;
		boolean visited = false;
		ArrayList <Person> friends = new ArrayList <Person> ();
		ArrayList <Person> foes = new ArrayList <Person> ();

		public Person(Scanner sc, int i)
		{
			id = i;
		}
	}

	static ArrayList <Person> inComponent = new ArrayList <Person> ();
	static boolean[] inComponentB;

	private static void floodFill(Person person)
	{
		if(person.visited) return;
		inComponent.add(person);
		person.visited = true;
		for(Person f : person.friends)
			floodFill(f);
	}

	public static void main(String[] args)
	{
		Scanner sc = new Scanner();
		int n = sc.nextInt();
		Person[] allPersons = sc.nextObjectArray(Person.class, n);
		inComponentB = new boolean[n];
		int k = sc.nextInt();
		for(int i = 0; i < k; i++)
		{
			int u = sc.nextInt() - 1;
			int v = sc.nextInt() - 1;
			allPersons[u].friends.add(allPersons[v]);
			allPersons[v].friends.add(allPersons[u]);
		}
		int m = sc.nextInt();
		for(int i = 0; i < m; i++)
		{
			int u = sc.nextInt() - 1;
			int v = sc.nextInt() - 1;
			allPersons[u].foes.add(allPersons[v]);
			allPersons[v].foes.add(allPersons[u]);
		}
		int best = 0;
		for(int i = 0; i < n; i++)
		{
			if(!allPersons[i].visited)
			{
				inComponent.clear();
				floodFill(allPersons[i]);
				for(Person p : inComponent)
					inComponentB[p.id] = true;
				boolean viable = true;
				for(Person p : inComponent)
					for(Person p1 : p.foes)
						if(inComponentB[p1.id])
							viable = false;
				for(Person p : inComponent)
					inComponentB[p.id] = false;
				if(viable)
					best = Math.max(best, inComponent.size());
			}
		}
		sc.printLine(best);
	}
}


import java.io.*;
import java.security.SecureRandom;
import java.util.*;
import java.math.*;
import java.awt.geom.*;

import static java.lang.Math.*;

public class Solution implements Runnable {

	int n, k, m;
	ArrayList<ArrayList<Integer>> friend = new ArrayList<>();
	ArrayList<ArrayList<Integer>> enemy = new ArrayList<>();
	boolean used[];
	boolean dfs(int s) {
		used[s] = true;
		for (int i : friend.get(s)) {
			if (!used[i]) {
				dfs(i);
				for (int j : enemy.get(i)) {
					if (used[j]) {
						return false;
					}
				}
			}
		}
		return true;
	}
	public void solve() throws Exception {
		n = sc.nextInt();
		k = sc.nextInt();
		for (int i = 0;i < n; ++ i) {
			friend.add(new ArrayList<Integer>());
			enemy.add(new ArrayList<Integer>());
		}
		for (int i = 0;i < k; ++ i) {
			int s = sc.nextInt() - 1;
			int t = sc.nextInt() - 1;
			friend.get(s).add(t);
			friend.get(t).add(s);
		}
		m = sc.nextInt();
		for (int i = 0;i < m; ++ i) {
			int s = sc.nextInt() - 1;
			int t = sc.nextInt() - 1;
			enemy.get(s).add(t);
			enemy.get(t).add(s);
		}
		int ans = 0;
		used = new boolean[n];

		for (int i = 0;i < n; ++ i) {
			Arrays.fill(used, false);
			if (dfs(i)) {
				int col = 0;
				boolean can = true;
				for (int ii = 0;ii < n; ++ ii) {
					if (used[ii]) {
						++ col;
						for (int j : enemy.get(ii)) {
							if (used[j]) {
								can = false;
							}
						}
					}
				}
				if (can)
					ans = max(ans, col);
			}
		}
		out.println(ans);
    }

    /*--------------------------------------------------------------*/

    static String filename = "";
    static boolean fromFile = false;

    BufferedReader in;
    PrintWriter out;
    FastScanner sc;

    public static void main(String[] args) {
        new Thread(null, new Solution(), "", 1 << 25).start();
    }

    public void run() {
        try {
            init();
            solve();
        } catch (Exception e) {
            throw new RuntimeException(e);
        } finally {
            out.close();
        }
    }

    void init() throws Exception {
    	if (fromFile) {
    		in = new BufferedReader(new FileReader(filename+".in"));
        	out = new PrintWriter(new FileWriter(filename+".out"));
    	} else {
    		in = new BufferedReader(new InputStreamReader(System.in));
        	out = new PrintWriter(System.out);
    	}
        sc = new FastScanner(in);
    }
}

class FastScanner {

    BufferedReader reader;
    StringTokenizer strTok;

    public FastScanner(BufferedReader reader) {
        this.reader = reader;
    }

    public String nextToken() throws IOException {
        while (strTok == null || !strTok.hasMoreTokens()) {
            strTok = new StringTokenizer(reader.readLine());
        }

        return strTok.nextToken();
    }

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

    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }

    public BigInteger nextBigInteger() throws IOException {
    	return new BigInteger(nextToken());
    }

    public BigDecimal nextBigDecimal() throws IOException {
    	return new BigDecimal(nextToken());
    }
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Main {
	public static BufferedReader in;
	public static PrintWriter out;

	public static void main(String[] args) throws IOException {
		in = new BufferedReader(new InputStreamReader(System.in));
		out = new PrintWriter(System.out);

		boolean showLineError = true;
		if (showLineError) {
			solve();
			out.close();
		} else {
			try {
				solve();
			} catch (Exception e) {
			} finally {
				out.close();
			}
		}

	}

	static void debug(Object... os) {
		out.println(Arrays.deepToString(os));
	}
	private static int comp;

	private static void solve() throws IOException {
		int n = Integer.parseInt(in.readLine());
		int m1 = Integer.parseInt(in.readLine());
		List<Integer>[] g = (List<Integer>[]) new List[n];
		for(int i =0;i<n;i++)
			g[i]= new ArrayList<Integer>();
		for(int i =0;i<m1;i++){
			String[] line = in.readLine().split(" ");
			int u = Integer.parseInt(line[0])-1;
			int v = Integer.parseInt(line[1])-1;
			g[u].add(v);
			g[v].add(u);
		}
		int[] ok =new int[n];
		Arrays.fill(ok, -1);
		List<Integer> size=new ArrayList<Integer>();
		for(int i =0;i<n;i++)
			if(ok[i]==-1){
				ok[i]=comp;
				size.add(dfs(g,ok,i));
				comp++;
			}
		int m2 = Integer.parseInt(in.readLine());
		for(int i =0;i<m2;i++){
			String[] line = in.readLine().split(" ");
			int u = Integer.parseInt(line[0])-1;
			int v = Integer.parseInt(line[1])-1;

			if(ok[u]==ok[v])
				size.set(ok[u], 0);
		}
		int ret= 0;
		for(int a : size)
			ret = Math.max(ret, a);
		out.println(ret);
	}

	private static int dfs(List<Integer>[] g, int[] ok, int u) {
		int ret=1;
		for(int v : g[u]){
			if(ok[v]==-1){
				ok[v]=comp;
				ret+=dfs(g,ok,v);
			}
		}
		return ret;
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.StreamTokenizer;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;

public class C {
    static InputStreamReader in = new InputStreamReader(System.in);
    static BufferedReader bf = new BufferedReader(in);
    static StreamTokenizer st = new StreamTokenizer(bf);
    static int n, k, m, cnt;
    static int [][] endes;
    static boolean []used,t;
    static boolean f;
    static Set<Integer> []s;
    public static void main(String[] args) throws IOException {
        n = nextInt();
        k = nextInt();
        endes = new int[n + 1][n+1];
        used = new boolean [n+1];
        for (int i = 1; i <= k; i++) {
            int v = nextInt();
            int u = nextInt();
            endes[v][u] = endes[u][v] = 1;
        }
        m = nextInt();
        for (int i = 0; i < m; i++) {
            int u = nextInt();
            int v = nextInt();
            endes[v][u] = endes[u][v] = 2;
        }
        int ans = 0;
        t = new boolean [n+1];
        for (int i = 1; i <=n; i++) {
            if (!used[i]){
                Arrays.fill(t, false);
                Queue<Integer> queue = new LinkedList<Integer>();
                t[i] = true;
                queue.add(i);
                boolean f = true;
                used[i] = true;
                int cnt = 0;
                while (!queue.isEmpty()){
                    int v = queue.poll();
                    for (int j = 1; j <=n; j++) {
                        if (endes[v][j] == 1){
                            if (!used[j]){
                                used[j] = t[j] = true;
                                queue.add(j);
                                cnt++;
                            }
                        }else{
                            if (endes[v][j] == 2){
                                if (t[j]){
                                    f = false;
                                }
                            }
                        }
                    }
                }
                if (f){
                    ans = Math.max(ans, cnt+1);
                }
            }
        }
        System.out.println(ans);
    }
        private static int nextInt() throws IOException {
        st.nextToken();
        return (int) st.nval;
    }
}


/*
 ID: govind.3, GhpS, govindpatel
 LANG: JAVA
 TASK: Main
 */

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {

    /**
     * Min segment Tree takes the minimum number at the root
     */
    class MinSegmentTree {

        /**
         * root: Tree root, balance: input array, rl,rr:
         * rl=0,rr=inputArray.length-1 minTree:segment Tree
         */
        private void initMinTree(int root, int rl, int rr, int[] balance, int[] minTree) {
            if (rl == rr) {
                minTree[root] = balance[rl];
                return;
            }
            int rm = (rl + rr) / 2;
            initMinTree(root * 2 + 1, rl, rm, balance, minTree);
            initMinTree(root * 2 + 2, rm + 1, rr, balance, minTree);
            minTree[root] = Math.min(minTree[root * 2 + 1], minTree[root * 2 + 2]);
        }

        /**
         * minTree:segment tree root:0 rl:0,rr:inputarray.length-1
         * l=queryleft-1(If 1 based index),r = queryright(1-based)
         */
        private int getMin(int[] minTree, int root, int rl, int rr, int l, int r) {
            //l = query left-1, r = query right
            if (l > r) {
                return Integer.MAX_VALUE;
            }
            if (l == rl && r == rr) {
                return minTree[root];
            }
            int rm = (rl + rr) / 2;
            return Math.min(getMin(minTree, root * 2 + 1, rl, rm, l, Math.min(r, rm)),
                    getMin(minTree, root * 2 + 2, rm + 1, rr, Math.max(rm + 1, l), r));
        }
    }
    //dsu next operation
    int[] next;

    private int next(int i) {
        if (next[i] == i) {
            return i;
        }
        return next[i] = next(next[i]);
    }

    //segment tree...
    private void set(int[] t, int ind, int val) {
        ind += (t.length / 2);
        t[ind] = val;
        int curr = 0;
        while (ind > 1) {
            ind >>= 1;
            if (curr == 0) {
                t[ind] = t[ind * 2] | t[ind * 2 + 1];
            } else {
                t[ind] = t[ind * 2] ^ t[2 * ind + 1];
            }
            curr ^= 1;
        }
    }

    //Binary Index tree
    class FenwickTree {

        int[] ft;
        int N;

        FenwickTree(int n) {
            this.N = n;
            ft = new int[N];
        }

        private int lowbit(int x) {
            return x & (-x);
        }

        void update(int pos, int val) {
            while (pos < N) {
                ft[pos] += val;
                pos |= pos + 1;//0-index
            }
        }

        int sum(int pos) {
            int sum = 0;
            while (pos >= 0) {
                sum += ft[pos];
                pos = (pos & (pos + 1)) - 1;
            }
            return sum;
        }

        int rangeSum(int left, int right) {
            return sum(right) - sum(left - 1);
        }
    }

    /**
     * BINARY SEARCH IN FENWICK TREE: l=1, r=N(length), at=sumRequired,
     * letter=TreeIndex(if there are many ft), ft=arrays of FT
     */
    private int binarySearch(int l, int r, int at, int letter, FenwickTree[] ft) {
        while (r - l > 0) {
            int mid = (l + r) / 2;
            int sum = ft[letter].sum(mid);
            if (sum < at) {
                l = mid + 1;
            } else {
                r = mid;
            }
        }
        return l;
    }

    private int[] compress(int[] a) {
        int[] b = new int[a.length];
        for (int i = 0; i < a.length; i++) {
            b[i] = a[i];
        }
        Arrays.sort(b);
        int m = 0;
        for (int i = 0; i < b.length;) {
            int j = i;
            while (j < b.length && b[j] == b[i]) {
                j++;
            }
            b[m++] = b[i];
            i = j;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = Arrays.binarySearch(b, 0, m, a[i]);
        }
        return a;
    }

    class Dijkstra {

        class Edge implements Comparable<Edge> {

            int to;
            long weight;

            Edge(int t, long w) {
                to = t;
                weight = w;
            }

            public int compareTo(Edge other) {
                return (int) Math.signum(weight - other.weight);
            }
        }
        public static final long INF = (long) 1e17;
        private ArrayList<Edge> adj[];
        private int nodes;
        private long[] dist;
        private int[] prev;
        private boolean[] visited;

        public Dijkstra(int n) {
            nodes = n;
            adj = new ArrayList[nodes];
            dist = new long[nodes];
            prev = new int[nodes];
            visited = new boolean[nodes];
            for (int i = 0; i < nodes; i++) {
                adj[i] = new ArrayList<Edge>();
                dist[i] = INF;
                prev[i] = -1;
            }
        }

        public void add(int u, int v, long cost) {
            adj[u].add(new Edge(v, cost));
        }

        public void dist() {
            //src vertex = 0;
            dist[0] = 0;
            Queue<Edge> q = new PriorityQueue<Edge>();
            q.add(new Edge(0, 0));
            while (!q.isEmpty()) {
                Edge e = q.poll();
                int ind = e.to;
                if (visited[ind]) {
                    continue;
                }
                visited[ind] = true;

                for (Edge edge : adj[ind]) {
                    long newDistance = e.weight + edge.weight;
                    if (newDistance < dist[edge.to]) {
                        dist[edge.to] = newDistance;
                        prev[edge.to] = ind;
                        q.add(new Edge(edge.to, dist[edge.to]));
                    }
                }
            }
        }

        public ArrayList<Integer> getPrevList(int last) {
            ArrayList<Integer> al = new ArrayList<Integer>();
            while (last != -1) {
                al.add(last);
                last = prev[last];
            }
            return al;
        }

        public int[] getPrev() {
            return prev;
        }

        public long[] getDistance() {
            return dist;
        }

        public boolean[] getVisited() {
            return visited;
        }
    }

    class Edge {

        int id, to, cap;
        boolean rev;

        Edge(int to, int id, int cap, boolean rev) {
            this.to = to;
            this.id = id;
            this.cap = cap;
            this.rev = rev;
        }
    }
    int[] p;

    private void solve() throws IOException {
        int N = nextInt();
        int M = nextInt();
        p = new int[2005];
        for (int i = 0; i < N; i++) {
            p[i] = i;
        }
        for (int i = 0; i < M; i++) {
            int f1 = nextInt() - 1;
            int f2 = nextInt() - 1;
            merge(f1, f2);
        }
        boolean[] good = new boolean[N];
        int[] size = new int[N];
        for (int i = 0; i < N; i++) {
            size[get(i)]++;
            good[i] = true;
        }
        int E = nextInt();
        for (int i = 0; i < E; i++) {
            int e1 = nextInt() - 1;
            int e2 = nextInt() - 1;
            int pe1 = get(e1);
            int pe2 = get(e2);
            if (pe1 == pe2) {
                good[pe1] = false;
            }
        }
        int ans = 0;
        for (int i = 0; i < N; i++) {
            if (good[i]) {
                ans = Math.max(ans, size[i]);
            }
        }
        out.println(ans);
    }

    void merge(int a, int b) {
        a = get(a);
        b = get(b);
        if (a != b) {
            p[a] = b;
        }
    }

    int get(int a) {
//        if (p[a] == a) {
//            return a;
//        }
        while (p[a] != a) {
            p[a] = p[p[a]];
            a = p[a];
        }
//        return p[a] = get(p[a]);
        return a;
    }

    boolean isSorted(ArrayList<Integer> al) {
        int size = al.size();
        for (int i = 1; i < size - 2; i++) {
            if (al.get(i) > al.get(i + 1)) {
                return false;
            }
        }
        return true;
    }

    /**
     * SHUFFLE: shuffle the array 'a' of size 'N'
     */
    private void shuffle(int[] a, int N) {
        for (int i = 0; i < N; i++) {
            int r = i + (int) ((N - i) * Math.random());
            int t = a[i];
            a[i] = a[r];
            a[r] = t;
        }
    }

    /**
     * TEMPLATE-STUFF: main method, run method - ( fileIO and stdIO ) and
     * various methods for input like nextInt, nextLong, nextToken and
     * nextDouble with some declarations.
     */
    /**
     * For solution to the problem ... see the solve method
     */
    public static void main(String[] args) {
        new Main().run();
    }

    public void run() {
        try {
            in = new BufferedReader(new FileReader("D-large.in"));
            out = new PrintWriter(new BufferedWriter(new FileWriter("Main.out")));
            tok = null;
            solve();
            in.close();
            out.close();
            System.exit(0);
        } catch (IOException e) {//(FileNotFoundException e) {
            try {
                in = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
                tok = null;
                solve();
                in.close();
                out.close();
                System.exit(0);
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
                System.exit(0);
            }
        }
    }

    private String nextToken() throws IOException {
        while (tok == null || !tok.hasMoreTokens()) {
            tok = new StringTokenizer(in.readLine());
        }
        return tok.nextToken();
    }

    private int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    private long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    private double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
    BufferedReader in;
    StringTokenizer tok;
    PrintWriter out;
}


import java.util.*;
import java.io.*;

public class Main implements Runnable {

    boolean[] visited;

    public void solve() throws IOException {
        int n = nextInt();
        int m = nextInt();
        int[] p = new int[n];
        for (int i = 0; i < n; i++) {
            p[i] = i;
        }
        for (int i = 0; i < m; i++) {
            int a = nextInt() - 1;
            int b = nextInt() - 1;
            merge(p, a, b);
        }
        boolean[] good = new boolean[n];

        int[] size = new int[n];
        for (int i = 0; i < n; i++) {
            size[get(p, i)]++;
            good[i] = true;
        }
        m = nextInt();
        for (int i = 0; i < m; i++) {
            int a = nextInt() - 1;
            int b = nextInt() - 1;
            if (get(p, a) == get(p, b)) {
                good[get(p, a)] = false;
            }
        }
        int ans = 0;
        for (int i = 0; i < n; i++) {
            if (good[i]) {
                ans = Math.max(ans, size[i]);
            }
        }
        System.out.println(ans);
    }

    void dfs(boolean[][] board, int ind) {
        visited[ind] = true;
        for (int i = 0; i < board.length; i++) {
            if (board[ind][i] && !visited[i]) {
                dfs(board, i);
            }
        }

    }

    int answer(int[] a, int[] b) {
        int n = a.length;
        b = b.clone();
        a = a.clone();
        for (int i = 0; i < n; i++) {
            if (b[i] >= 0) {
                merge(a, i, b[i]);
            }
        }
        int cnt = 0;
        for (int i = 0; i < n; i++) {
            if (a[i] < 0) {
                cnt++;
            }
        }
        return cnt;
    }

    void merge(int[] arr, int a, int b) {
        a = get(arr, a);
        b = get(arr, b);
        if (a != b) {
            arr[a] = b;
        }
    }

    int get(int[] arr, int a) {
        if (arr[a] == a) {
            return a;
        }
        return arr[a] = get(arr, arr[a]);
    }

    void shuffle(int[] a) {
        int N = a.length;
        for (int i = 0; i < N / 2; i++) {
            int j = (int) (Math.random() * N);
            int t = a[i];
            a[i] = a[j];
            a[j] = t;
        }
    }

    void print(int[] a) {
        System.out.println();
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i] + " ");
        }
    }

    void print(int[][] arr) {
        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }

    void print(boolean[][] arr) {
        System.out.println();
        for (int i = 0; i < arr.length; i++) {
            for (int j = 0; j < arr[i].length; j++) {
                System.out.print(arr[i][j] + " ");
            }
            System.out.println();
        }
    }

    boolean nextPermutation(int[] arr) {
        int f = -1;
        for (int i = arr.length - 2; i >= 0; i--) {
            if (arr[i + 1] > arr[i]) {
                f = i;
                break;
            }
        }
        if (f == -1) {
            return false;
        }
        int s = -1;
        for (int i = arr.length - 1; i >= 0; i--) {
            if (arr[i] > arr[f]) {
                s = i;
                break;
            }
        }
        int d = arr[f];
        arr[f] = arr[s];
        arr[s] = d;

        f++;
        int l = arr.length - 1;
        while (f < l) {
            d = arr[f];
            arr[f] = arr[l];
            arr[l] = d;
            f++;
            l--;
        }
        return true;
    }

    //-----------------------------------------------------------
    public static void main(String[] args) {
        new Main().run();
    }

    public void run() {
        try {
            in = new BufferedReader(new InputStreamReader(System.in));
            tok = null;
            solve();
            in.close();
        } catch (IOException e) {
            System.exit(0);
        }
    }

    public String nextToken() throws IOException {
        while (tok == null || !tok.hasMoreTokens()) {
            tok = new StringTokenizer(in.readLine());
        }
        return tok.nextToken();
    }

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

    public long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
    BufferedReader in;
    StringTokenizer tok;
}


/*
 ID: govind.3, GhpS, govindpatel
 LANG: JAVA
 TASK: Main
 */

import java.io.*;
import java.math.BigInteger;
import java.util.*;

public class Main {

    /**
     * Min segment Tree takes the minimum number at the root
     */
    class MinSegmentTree {

        /**
         * root: Tree root, balance: input array, rl,rr:
         * rl=0,rr=inputArray.length-1 minTree:segment Tree
         */
        private void initMinTree(int root, int rl, int rr, int[] balance, int[] minTree) {
            if (rl == rr) {
                minTree[root] = balance[rl];
                return;
            }
            int rm = (rl + rr) / 2;
            initMinTree(root * 2 + 1, rl, rm, balance, minTree);
            initMinTree(root * 2 + 2, rm + 1, rr, balance, minTree);
            minTree[root] = Math.min(minTree[root * 2 + 1], minTree[root * 2 + 2]);
        }

        /**
         * minTree:segment tree root:0 rl:0,rr:inputarray.length-1
         * l=queryleft-1(If 1 based index),r = queryright(1-based)
         */
        private int getMin(int[] minTree, int root, int rl, int rr, int l, int r) {
            //l = query left-1, r = query right
            if (l > r) {
                return Integer.MAX_VALUE;
            }
            if (l == rl && r == rr) {
                return minTree[root];
            }
            int rm = (rl + rr) / 2;
            return Math.min(getMin(minTree, root * 2 + 1, rl, rm, l, Math.min(r, rm)),
                    getMin(minTree, root * 2 + 2, rm + 1, rr, Math.max(rm + 1, l), r));
        }
    }
    //dsu next operation
    int[] next;

    private int next(int i) {
        if (next[i] == i) {
            return i;
        }
        return next[i] = next(next[i]);
    }

    //segment tree...
    private void set(int[] t, int ind, int val) {
        ind += (t.length / 2);
        t[ind] = val;
        int curr = 0;
        while (ind > 1) {
            ind >>= 1;
            if (curr == 0) {
                t[ind] = t[ind * 2] | t[ind * 2 + 1];
            } else {
                t[ind] = t[ind * 2] ^ t[2 * ind + 1];
            }
            curr ^= 1;
        }
    }

    //Binary Index tree
    class FenwickTree {

        int[] ft;
        int N;

        FenwickTree(int n) {
            this.N = n;
            ft = new int[N];
        }

        private int lowbit(int x) {
            return x & (-x);
        }

        void update(int pos, int val) {
            while (pos < N) {
                ft[pos] += val;
                pos |= pos + 1;//0-index
            }
        }

        int sum(int pos) {
            int sum = 0;
            while (pos >= 0) {
                sum += ft[pos];
                pos = (pos & (pos + 1)) - 1;
            }
            return sum;
        }

        int rangeSum(int left, int right) {
            return sum(right) - sum(left - 1);
        }
    }

    /**
     * BINARY SEARCH IN FENWICK TREE: l=1, r=N(length), at=sumRequired,
     * letter=TreeIndex(if there are many ft), ft=arrays of FT
     */
    private int binarySearch(int l, int r, int at, int letter, FenwickTree[] ft) {
        while (r - l > 0) {
            int mid = (l + r) / 2;
            int sum = ft[letter].sum(mid);
            if (sum < at) {
                l = mid + 1;
            } else {
                r = mid;
            }
        }
        return l;
    }

    private int[] compress(int[] a) {
        int[] b = new int[a.length];
        for (int i = 0; i < a.length; i++) {
            b[i] = a[i];
        }
        Arrays.sort(b);
        int m = 0;
        for (int i = 0; i < b.length;) {
            int j = i;
            while (j < b.length && b[j] == b[i]) {
                j++;
            }
            b[m++] = b[i];
            i = j;
        }
        for (int i = 0; i < a.length; i++) {
            a[i] = Arrays.binarySearch(b, 0, m, a[i]);
        }
        return a;
    }

    class Dijkstra {

        class Edge implements Comparable<Edge> {

            int to;
            long weight;

            Edge(int t, long w) {
                to = t;
                weight = w;
            }

            public int compareTo(Edge other) {
                return (int) Math.signum(weight - other.weight);
            }
        }
        public static final long INF = (long) 1e17;
        private ArrayList<Edge> adj[];
        private int nodes;
        private long[] dist;
        private int[] prev;
        private boolean[] visited;

        public Dijkstra(int n) {
            nodes = n;
            adj = new ArrayList[nodes];
            dist = new long[nodes];
            prev = new int[nodes];
            visited = new boolean[nodes];
            for (int i = 0; i < nodes; i++) {
                adj[i] = new ArrayList<Edge>();
                dist[i] = INF;
                prev[i] = -1;
            }
        }

        public void add(int u, int v, long cost) {
            adj[u].add(new Edge(v, cost));
        }

        public void dist() {
            //src vertex = 0;
            dist[0] = 0;
            Queue<Edge> q = new PriorityQueue<Edge>();
            q.add(new Edge(0, 0));
            while (!q.isEmpty()) {
                Edge e = q.poll();
                int ind = e.to;
                if (visited[ind]) {
                    continue;
                }
                visited[ind] = true;

                for (Edge edge : adj[ind]) {
                    long newDistance = e.weight + edge.weight;
                    if (newDistance < dist[edge.to]) {
                        dist[edge.to] = newDistance;
                        prev[edge.to] = ind;
                        q.add(new Edge(edge.to, dist[edge.to]));
                    }
                }
            }
        }

        public ArrayList<Integer> getPrevList(int last) {
            ArrayList<Integer> al = new ArrayList<Integer>();
            while (last != -1) {
                al.add(last);
                last = prev[last];
            }
            return al;
        }

        public int[] getPrev() {
            return prev;
        }

        public long[] getDistance() {
            return dist;
        }

        public boolean[] getVisited() {
            return visited;
        }
    }

    class Edge {

        int id, to, cap;
        boolean rev;

        Edge(int to, int id, int cap, boolean rev) {
            this.to = to;
            this.id = id;
            this.cap = cap;
            this.rev = rev;
        }
    }
    int[] p;

    private void solve() throws IOException {
        int N = nextInt();
        int M = nextInt();
        p = new int[2005];
        for (int i = 0; i < N; i++) {
            p[i] = i;
        }
        for (int i = 0; i < M; i++) {
            int f1 = nextInt() - 1;
            int f2 = nextInt() - 1;
            merge(f1, f2);
        }
        boolean[] good = new boolean[N];
        int[] size = new int[N];
        for (int i = 0; i < N; i++) {
            size[get(i)]++;
            good[i] = true;
        }
        int E = nextInt();
        for (int i = 0; i < E; i++) {
            int e1 = nextInt() - 1;
            int e2 = nextInt() - 1;
            int pe1 = get(e1);
            int pe2 = get(e2);
            if (pe1 == pe2) {
                good[pe1] = false;
            }
        }
        int ans = 0;
        for (int i = 0; i < N; i++) {
            if (good[i]) {
                ans = Math.max(ans, size[i]);
            }
        }
        out.println(ans);
    }

    void merge(int a, int b) {
        a = get(a);
        b = get(b);
        if (a != b) {
            p[a] = b;
        }
    }

    int get(int a) {
        if (p[a] == a) {
            return a;
        }
//        while (p[a] != a) {
//            p[a] = p[p[a]];
//            a = p[a];
//        }
        return p[a] = get(p[a]);
    }

    boolean isSorted(ArrayList<Integer> al) {
        int size = al.size();
        for (int i = 1; i < size - 2; i++) {
            if (al.get(i) > al.get(i + 1)) {
                return false;
            }
        }
        return true;
    }

    /**
     * SHUFFLE: shuffle the array 'a' of size 'N'
     */
    private void shuffle(int[] a, int N) {
        for (int i = 0; i < N; i++) {
            int r = i + (int) ((N - i) * Math.random());
            int t = a[i];
            a[i] = a[r];
            a[r] = t;
        }
    }

    /**
     * TEMPLATE-STUFF: main method, run method - ( fileIO and stdIO ) and
     * various methods for input like nextInt, nextLong, nextToken and
     * nextDouble with some declarations.
     */
    /**
     * For solution to the problem ... see the solve method
     */
    public static void main(String[] args) {
        new Main().run();
    }

    public void run() {
        try {
            in = new BufferedReader(new FileReader("D-large.in"));
            out = new PrintWriter(new BufferedWriter(new FileWriter("Main.out")));
            tok = null;
            solve();
            in.close();
            out.close();
            System.exit(0);
        } catch (IOException e) {//(FileNotFoundException e) {
            try {
                in = new BufferedReader(new InputStreamReader(System.in));
                out = new PrintWriter(new OutputStreamWriter(System.out));
                tok = null;
                solve();
                in.close();
                out.close();
                System.exit(0);
            } catch (IOException ex) {
                System.out.println(ex.getMessage());
                System.exit(0);
            }
        }
    }

    private String nextToken() throws IOException {
        while (tok == null || !tok.hasMoreTokens()) {
            tok = new StringTokenizer(in.readLine());
        }
        return tok.nextToken();
    }

    private int nextInt() throws IOException {
        return Integer.parseInt(nextToken());
    }

    private long nextLong() throws IOException {
        return Long.parseLong(nextToken());
    }

    private double nextDouble() throws IOException {
        return Double.parseDouble(nextToken());
    }
    BufferedReader in;
    StringTokenizer tok;
    PrintWriter out;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 2001;

int n, k, m;

int rnk[N], parent[N], num[N];

bool mp[N];

void make_set(int v)
{
    num[v] = 1;
    parent[v] = v;
    rnk[v] = 0;
}

int find_set(int v)
{
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_set(int a, int b)
{
    int x = find_set(a);
    int y = find_set(b);
    if (x != y)
    {
        if (rnk[x] < rnk[y])
        {
            swap(x, y);
            swap(a, b);
        }
        if (rnk[x] == rnk[y])
            rnk[x]++;
        parent[y] = x;
        num[x] += num[y];
    }
}

int main()
{
    freopen( "input.txt", "r", stdin);
    freopen( "output.txt", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        make_set(i);
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        int x, y;
        cin >> x >> y;
        union_set(x, y);
    }
    cin >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (find_set(x) == find_set(y))
            mp[find_set(x)] = 1;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int f = find_set(i);
        if (mp[f])
            continue;
        ans = max(num[f], ans);
    }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 2001;

int n, k, m;

int rnk[N], parent[N], num[N];

bool mp[N];

void make_set(int v)
{
    num[v] = 1;
    parent[v] = v;
    rnk[v] = 0;
}

int find_set(int v)
{
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_set(int a, int b)
{
    int x = find_set(a);
    int y = find_set(b);
    if (x != y)
    {
        if (rnk[x] < rnk[y])
        {
            swap(x, y);
            swap(a, b);
        }
        if (rnk[x] == rnk[y])
            rnk[x]++;
        parent[y] = x;
        num[a] += num[b];
    }
}

int main()
{
    freopen( "input.txt", "r", stdin);
    freopen( "output.txt", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        make_set(i);
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        int x, y;
        cin >> x >> y;
        union_set(x, y);
    }
    cin >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (find_set(x) == find_set(y))
            mp[find_set(x)] = 1;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int f = find_set(i);
        if (mp[f])
            continue;
        ans = max(num[f], ans);
    }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 2001;

int n, k, m;

int rnk[N], parent[N], num[N];

bool mp[N];

void make_set(int v)
{
    num[v] = 1;
    parent[v] = v;
    rnk[v] = 0;
}

int find_set(int v)
{
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_set(int a, int b)
{
    int x = find_set(a);
    int y = find_set(b);
    if (x != y)
    {
        if (rnk[x] < rnk[y])
        {
            swap(x, y);
            swap(a, b);
        }
        if (rnk[x] == rnk[y])
            rnk[x]++;
        parent[y] = x;
        num[x] += num[y];
    }
}

int main()
{
    //freopen( "input.txt", "r", stdin);
    //freopen( "output.txt", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        make_set(i);
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        int x, y;
        cin >> x >> y;
        union_set(x, y);
    }
    cin >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (find_set(x) == find_set(y))
            mp[find_set(x)] = 1;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int f = find_set(i);
        if (mp[f])
            continue;
        ans = max(num[f], ans);
    }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 2001;

int n, k, m;

int rnk[N], parent[N], num[N];

bool mp[N];

void make_set(int v)
{
    num[v] = 1;
    parent[v] = v;
    rnk[v] = 0;
}

int find_set(int v)
{
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_set(int a, int b)
{
    int x = find_set(a);
    int y = find_set(b);
    if (x != y)
    {
        if (rnk[x] < rnk[y])
        {
            swap(x, y);
            swap(a, b);
        }
        if (rnk[x] == rnk[y])
            rnk[x]++;
        parent[y] = x;
        num[a] += num[b];
    }
}

int main()
{
    //freopen( "input.txt", "r", stdin);
    //freopen( "output.txt", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        make_set(i);
    cin >> k;
    for (int i = 0; i < n; i++)
    {
        int x, y;
        cin >> x >> y;
        union_set(x, y);
    }
    cin >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (find_set(x) == find_set(y))
            mp[find_set(x)] = 1;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int f = find_set(i);
        if (mp[f])
            continue;
        ans = max(num[f], ans);
    }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

const int N = 2001;

int n, k, m;

int rnk[N], parent[N], num[N];

bool mp[N];

void make_set(int v)
{
    num[v] = 1;
    parent[v] = v;
    rnk[v] = 0;
}

int find_set(int v)
{
    if (v == parent[v])
        return v;
    return parent[v] = find_set(parent[v]);
}

void union_set(int a, int b)
{
    int x = find_set(a);
    int y = find_set(b);
    if (x != y)
    {
        if (rnk[x] < rnk[y])
        {
            swap(x, y);
            swap(a, b);
        }
        if (rnk[x] == rnk[y])
            rnk[x]++;
        parent[y] = x;
        num[a] += num[b];
    }
}

int main()
{
    //freopen( "input.txt", "r", stdin);
    //freopen( "output.txt", "w", stdout);
    cin >> n;
    for (int i = 1; i <= n; i++)
        make_set(i);
    cin >> k;
    for (int i = 0; i < k; i++)
    {
        int x, y;
        cin >> x >> y;
        union_set(x, y);
    }
    cin >> m;
    for (int i = 0; i < m; i++)
    {
        int x, y;
        cin >> x >> y;
        if (find_set(x) == find_set(y))
            mp[find_set(x)] = 1;
    }
    int ans = 0;
    for (int i = 1; i <= n; i++)
    {
        int f = find_set(i);
        if (mp[f])
            continue;
        ans = max(num[f], ans);
    }
    cout << ans;
    return 0;
}


#include <bits/stdc++.h>

using namespace std;

vector<int>G[2005];
int a[100005], b[100005];
int w[2005];
int sz[2005];
int c;

void dfs(int node) {
  w[node] = c;
  sz[c]++;
  for (auto it:G[node])
    if (!w[it])
      dfs(it);
}

int main() {
  int n, m, k;
  scanf("%d%d", &n, &m);
  for (int i = 1; i <= m; ++i) {
    int u, v;
    scanf("%d%d", &u, &v);
    G[u].push_back(v);
    G[v].push_back(u);
  }
  scanf("%d", &k);
  for (int i = 1; i <= k; ++i)
    scanf("%d%d", &a[i], &b[i]);

  for (int i = 1; i <= n; ++i)
    if (!w[i]) {
      c++;
      dfs(i);
    }

  for (int i = 1; i <= k; ++i)
    if (w[a[i]] == w[b[i]])
      sz[w[a[i]]] = 0;
  int ans = 0;
  for (int i = 1; i <= c; ++i)
    ans = max(ans, sz[i]);
  printf("%d\n", ans);

  return 0;
}


#include<bits/stdc++.h>
using namespace std;

typedef vector < int > vi;
const int N = 2020;

int p[N] , sz[N];
bool hate[N][N];

vi v[N];
set < int > st;

int get(int x){
    if(x == p[x])return x;
    return  p[x] = get(p[x]);
}

void join(int x , int y){
    x = get(x);
    y = get(y);

    if(x == y)return;

    if(rand() & 1)swap(x , y);
    p[x] = y;
    sz[y] += sz[x];
}

void input_edges(bool b){

    int m;
    scanf("%d" , &m);

    int u , v;
    for(int i = 1 ; i <= m ; i ++){
        scanf("%d %d" , &u , &v);

        if(b){
            join(u , v);
        }
        else {
            hate[u][v] = hate[v][u] = 1;
        }
    }
}

main(){

    for(int i = 1;  i < N ; i ++)p[i] = i , sz[i] = 1;

    int n;

    scanf("%d" , &n);
    input_edges(1);
    input_edges(0);

    for(int i = 1 ; i <= n ; i ++){
        v[get(i)].push_back(i);
        st.insert(get(i));
    }

    int mx = 0;
    for(auto S : st){

        bool ok = 1;
        for(auto ss : v[S]){
            for(auto ss2 : v[S])
                if(hate[ss][ss2]){
                    ok = 0;
                    break;
                }
            if(ok == 0)break;
        }
        if(ok)mx = max(mx , sz[S]);
    }

    printf("%d\n" , mx);

}


/**
 *  “Experience is the name everyone gives to their mistakes.” – Oscar Wilde
 *
 *  author  :   prodipdatta7
 *  created :   Thursday 05-March, 2020  09:27:17 PM
**/

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

// #pragma GCC optimize("Ofast")
// #pragma GCC target("avx,avx2,fma")
// #pragma GCC optimize("unroll-loops")

using namespace std ;
using namespace __gnu_pbds ;

#define     ll          long long
#define     ld          long double
#define     ull         unsigned long long
#define     pii         pair<int,int>
#define     pll         pair<ll,ll>
#define     vi          vector<int>
#define     vll         vector<ll>
#define     vvi         vector<vector<int>>
#define     debug(x)    cerr << #x << " = " << x << '\n' ;
#define     rep(i,b,e)  for(__typeof(e) i = (b) ; i != (e + 1) - 2 * ((b) > (e))  ; i += 1 - 2 * ((b) > (e)))
#define     all(x)      x.begin() , x.end()
#define     rall(x)     x.rbegin() , x.rend()
#define     sz(x)       (int)x.size()
#define     ff          first
#define     ss          second
#define     pb          push_back
#define     eb          emplace_back
#define     mem(a)      memset(a , 0 ,sizeof a)
#define     memn(a)     memset(a , -1 ,sizeof a)
#define     fread       freopen("input.txt","r",stdin)
#define     fwrite      freopen("output.txt","w",stdout)
#define     TN          typename

typedef tree <int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update > ordered_set;
typedef tree <int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update > ordered_multiset;

/*
Note :  There is a problem with erase() function in ordered_multiset (for less_equal<int> tag).
        lower_bound() works as upper_bound() and vice-versa.
        Be careful to use.
        i) find_by_order(k) : kth smallest element counting from 0 .
        ii) order_of_key(k) : number of elements strictly smaller than k.
*/

/*###############-> Input Section <-###############*/

template <TN T> inline void Int(T &a) {
    bool minus = false; a = 0; char ch = getchar();
    while (true) { if (ch == '-' or (ch >= '0' && ch <= '9')) break; ch = getchar(); }
    if (ch == '-') minus = true; else a = ch - '0';
    while (true) { ch = getchar(); if (ch < '0' || ch > '9') break; a = a * 10 + (ch - '0'); }
    if (minus)a *= -1 ;
}
template < TN T, TN T1 > inline void Int(T &a, T1 &b) {Int(a), Int(b) ;}
template < TN T, TN T1, TN T2 > inline void Int(T &a, T1 &b, T2 &c) {Int(a, b), Int(c) ;}
template < TN T, TN T1, TN T2, TN T3 > inline void Int(T &a, T1 &b, T2 &c, T3 &d) {Int(a, b), Int(c, d) ;}
template < TN T, TN T1, TN T2, TN T3, TN T4> inline void Int(T &a, T1 &b, T2 &c, T3 &d, T4 &e) {Int(a, b), Int(c, d, e) ;}

/*###############-> Debugger <-###############*/

#define error(args...) { string _s = #args; replace(_s.begin(), _s.end(), ',', ' '); stringstream _ss(_s); istream_iterator<string> _it(_ss); err(_it, args); }
void err(istream_iterator<string> it) {cout << endl ;}
template<TN T, TN... Args>
void err(istream_iterator<string> it, T a, Args... args) {
    cerr << *it << " = " << a << ' ' ;
    err(++it, args...);
}

/*###############-> Constraints <-###############*/

const int N          = (int)2e3 + 5 ;
const int maxN       = (int)1e6 + 6 ;
const ll  Mod        = (ll)1e9 + 7 ;
const int inf        = (int)2e9 ;
const ll  Inf        = (ll)1e18 ;
const int mod        = (int)1e9 + 7 ;

inline int add(int a, int b, int mod) {a += b ; return a >= mod ? a - mod : a ;}
inline int sub(int a, int b, int mod) {a -= b ; return a < 0 ? a + mod : a ;}
inline int mul(int a, int b, int mod) {return (ll)a * b % mod ;}

/*...... ! Code starts from here ! ......*/

int par[N], Rank[N], enemy[N] ;

int Find(int s){
    return par[s] = par[s] == s ? s : Find(par[s]) ;
}

void merge(int x, int y){
    x = Find(x), y = Find(y) ;
    if(x == y)return ;
    if(Rank[x] < Rank[y])swap(x, y) ;
    par[y] = x ;
    Rank[x] += Rank[y] ;
}

int main() {
    // ios_base::sync_with_stdio(false) ;
    // cin.tie(NULL) ; cout.tie(NULL) ;
    int test = 1 , tc = 0 ;
    //Int(test) ;
    while (test--) {
        int n ; Int(n) ;
        for(int i = 1 ; i <= n ; ++i)par[i] = i, Rank[i] = 1 ;
        int k ; Int(k) ;
        while(k--){
            int x, y ; Int(x, y) ;
            merge(x, y) ;
        }
        int m  ;Int(m) ;
        while(m--){
            int x, y ; Int(x, y) ;
            if(Find(x) == Find(y))enemy[Find(x)] = 1 ;
        }
        int res = 0 ;
        for(int i = 1 ; i <= n ; ++i){
            int p = Find(i) ;
            if(enemy[p])continue ;
            res = max(res, Rank[p]) ;
        }
        cout << res << '\n' ;
    }
    return 0 ;
}


/* -*- coding: utf-8; tab-width: 4 -*- */

#include <cstdio>
#include <queue>
#include <vector>

std::vector<int> e[2000];
bool t[2000][2000];

int
main()
{
	int n, k, u, v;
	bool d[2000] = {};
	std::queue<int> q;
	std::vector<int> w;
	int r(0);

	std::scanf("%d%d", &n, &k);
	while (0 < k--) {
		std::scanf("%d%d", &u, &v);
		--u, --v;
		e[u].push_back(v);
		e[v].push_back(u);
	}

	std::scanf("%d", &k);
	while (0 < k--) {
		std::scanf("%d%d", &u, &v);
		--u, --v;
		t[u][v] = t[v][u] = true;
	}

	for (int i(0); i < n; ++i) {
		if (d[i]) continue;

		q.push(i);
		while (!q.empty()) {
			int x = q.front();
			q.pop();
			if (d[x]) continue;
			d[x] = true;
			w.push_back(x);
			for (int y : e[x]) {
				if (!d[y]) q.push(y);
			}
		}

		for (int x : w) {
			for (int y : w) {
				if (t[x][y]) goto N;
			}
		}

		r = std::max<int>(r, w.size());

	N:
		w.clear();
	}

	std::printf("%d\n", r);

	return 0;
}


/* -*- coding: utf-8; tab-width: 4 -*- */

#include <cstdio>
#include <queue>
#include <vector>

std::vector<int> e[2000];
bool t[2000][2000];

int
main()
{
	int n, k, u, v;
	bool d[2000] = {};
	std::queue<int> q;
	std::vector<int> w;
	int r(0);

	std::scanf("%d%d", &n, &k);
	while (0 < k--) {
		std::scanf("%d%d", &u, &v);
		--u, --v;
		e[u].push_back(v);
		e[v].push_back(u);
	}

	std::scanf("%d", &k);
	while (0 < k--) {
		std::scanf("%d%d", &u, &v);
		--u, --v;
		t[u][v] = t[v][u] = true;
	}

	for (int i(0); i < n; ++i) {
		if (d[i]) continue;

		q.push(i);
		while (!q.empty()) {
			int x = q.front();
			q.pop();
			if (d[x]) continue;
			d[x] = true;
			w.push_back(x);
			for (int y : e[x]) {
				if (!d[y]) q.push(y);
			}
		}

		k = w.size();

		for (int i(0); i < k; ++i) {
			for (int j(i+1); j < k; ++j) {
				if (t[w[i]][w[j]]) goto N;
			}
		}

		r = std::max(r, k);

	N:
		w.clear();
	}

	std::printf("%d\n", r);

	return 0;
}


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <climits>
#include <cstdlib>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <list>
#include <unordered_map>
#include <bitset>
#include <algorithm>
#define ll long long int
#define e() cout << endl;
#define MA INT_MAX
#define MI INT_MIN
#define MOD 1000000007;
#define ppi pair <int,int>
#define scn(n) scanf("%d",&n)
#define vvi(n,m,x) vector <vector <int> > v(n,vector <int> (m,x));
#define cp(x,y) cout << "Case : " << x << " " << y << endl;
using namespace std;
const int MAXN = 5000;
int p[MAXN], size[MAXN], n, m;

int find_set( int v )
{
	return v == p[v] ? v : p[v] = find_set( p[v] );
}
void union_set( int x, int y )
{
	x = find_set( x );
	y = find_set( y );
	if( x != y ){
		if( size[x] < size[y] ) swap( x, y );
		p[x] = y;
		size[y] += size[x];
	}
}
int main()
{
        cin >> n >> m;
        for( int i = 1; i <= n; i++ ) size[i] = 1, p[i] = i;
        while( m-- ){
        	int x, y;
        	cin >> x >> y;
        	union_set( x, y );
        }
        int mx = 0;
        cin >> m;
        while( m-- ){
        	int x, y;
        	cin >> x >> y;
        	if( find_set( x ) == find_set( y ) )
        		size[find_set( x )] = 0;
        }
        for( int i = 1; i <= n; i++ ){
        	mx = max( mx, size[find_set( i )] );
        }
        cout << mx << endl;
}


#include <iostream>
#include <stdio.h>
#include <cstring>
#include <cmath>
#include <climits>
#include <cstdlib>
#include <vector>
#include <string>
#include <set>
#include <map>
#include <stack>
#include <queue>
#include <deque>
#include <list>
#include <unordered_map>
#include <bitset>
#include <algorithm>
#define ll long long int
#define e() cout << endl;
#define MA INT_MAX
#define MI INT_MIN
#define MOD 1000000007;
#define ppi pair <int,int>
#define scn(n) scanf("%d",&n)
#define vvi(n,m,x) vector <vector <int> > v(n,vector <int> (m,x));
#define cp(x,y) cout << "Case : " << x << " " << y << endl;
using namespace std;
map <int,set <int> > mp,enemy;
int level;
std::vector<bool> vis;

int dfs(int x)
{
	//cout << "called for : " << x << endl;
	for(int y : enemy[x])
		if(vis[y])
			return 0;

	level++;
	//cout << "passed enemy test\n";
	vis[x] = true;
	for(int y : mp[x])
	{
		if(!vis[y])
		{
			if(!dfs(y))
			{
				vis[x] = false;
				return 0;
			}
		}
	}

	return 1;
}
int main()
{
	int n,k,m;
	cin >> n >> k;
	vis = std::vector<bool> (n + 1,false);
	while(k--)
	{
		int a,b;
		cin >> a >> b;
		mp[a].insert(b);
		mp[b].insert(a);
	}
	cin >> m;
	while(m--)
	{
		int a,b;
		cin >> a >> b;
		enemy[a].insert(b);
		enemy[b].insert(a);
	}

	int ans = 0;
	for(int i = 1;i <= n;i++)
	{
		if(!vis[i])
		{
			level = 0;
			if(dfs(i))
			ans = max(ans,level);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <cmath>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include<cstdio>
#include<sstream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<map>
#include<set>
#include<queue>
#include<cctype>
#include <iomanip>
#include <string>
#include <sstream>

#include <functional>
#include <numeric>
#include <stack>
#include <climits>
#include <float.h>
#include<unordered_map>
#include <bitset>

using namespace std;

#define pb push_back
#define mp make_pair
#define ff first
#define ss second
#define rep(i, n) for(int i = 0; i < (n); ++i)
#define f(i,a,b) for(int i=a;i<b;i++)
#define F(i,a,b) for(int i=a;i>=    b;i--)
#define sz(a) ((int)a.size())
#define all(c) c.begin(), c.end()
#define fast ios_base::sync_with_stdio(0);cin.tie(NULL);cout.tie(NULL) ;
#define dbgs(x) cerr << (#x) << " --> " << (x) << ' '
#define dbg(x) cerr << (#x) << " --> " << (x) << endl
#define sz(a) ((int)a.size())
#define endl '\n'

//#define fast ios_base::sync_with_stdio(0);cin.tie(0) ;

typedef long long ll;
typedef unsigned long long ull;
typedef pair <ll, ll> pll;
typedef vector<ll> vll;
typedef vector<int> vi;

typedef vector<pair<int, int> > vpii;
typedef map<int, int> mii;
typedef map<ll, ll> mll;
typedef pair<int, int> pii;
typedef pair<string, int> psi;
typedef long double ld;

template <class T> const T& max(const T& a, const T&b, const T&c) { return max(a, max(b, c)); }

template <class T> const T& min(const T& a, const T&b, const T&c) { return min(a, min(b, c)); }

void sc(int &a) { scanf("%d", &a); }void sc(ll &a) { scanf("%lld", &a); }void sc(int& a, int& b) { sc(a); sc(b); }
void sc(ll &a, ll &b) { sc(a); sc(b); }void sc(int& a, int& b, int& c) { sc(a, b); sc(c); }void sc(ll& a, ll& b, ll& c) { sc(a, b); sc(c); }
void prl(int a) { printf("%d\n", a); }void prl(ll a) { printf("%lld\n", a); }void prl() { printf("\n"); }
void prs(int a) { printf("%d ", a); }void prs(ll a) { printf("%lld ", a); }

int gcd(int a, int b) { if (b == 0) return a; return gcd(b, a % b); }

ll lcm(ll a, ll b) { return (a * b) / gcd(a, b); }

ll poww(ll a, ll b) {

	if (b == 0) return 1;

	ll tmp = poww(a, b / 2);

	return (b & 1 ? a * tmp * tmp : tmp * tmp);

}

ll sumOfDigs(string s) { ll sum = 0; for (int i = 0; i < s.length(); i++) sum += s[i] - '0'; return sum; }

ll sumOfDigs(ll n) { return (n < 10 ? n : n % 10 + sumOfDigs(n / 10)); }

string itos(ll i) { string s = ""; 	while (i) { s += char(i % 10 + '0'); i /= 10; } reverse(all(s));  return s; }

ll stoi(string &s) { ll tot = 0; for (int i = (int)s.length() - 1, j = 1; i >= 0; i--, j *= 10) { tot += j * (s[i] + '0'); }  return tot; }

int months[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };

using namespace std;

#define PI acos((ld)-1.0)

// printf("%.8lf\n", sum * 1.0 / n);  // precision setting

ll mod = 1e9 + 7;

void tt() {

#ifndef online	_judge
	freopen("test.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);

#endif
}

ll modpower(ll x, ll y, ll p)
{

	x %= mod;

	if (!y) return 1;

	ll res = 1;

	if (y & 1) { res *= x;  res %= p; }

	ll z = modpower(x, y / 2, p);

	z %= p;

	z *= z;

	z %= mod;

	res *= z;

	res %= p;

	return res;

}

const int MAX = 2010;

vector<int> v[MAX];

int vis[MAX];

int col;

int c[MAX], cnt[MAX];

void dfs(int curr) {

	if (vis[curr]) { return;  }

	c[curr] = col;

	vis[curr] = 1;

	for (int i = 0; i < (int)v[curr].size(); i++) {

		dfs(v[curr][i]);

	}

	return;
}

int main() {

	fast;
	//tt();
	int n;
	cin >> n;

	int  k;
	cin >> k;

	for (int i = 1; i <= k; i++) {

		int a, b;
		cin >> a >> b;
		v[a].pb(b);
		v[b].pb(a);

	}

	for (int i = 1; i <= n; i++) {

		if (!vis[i]) {

			dfs(i);
			col++;

		}

	}
	/*cout << "col: " << col << endl;

	for (int i = 0; i < col; i++) cout << cnt[i] << " ";
	cout << endl;
*/
	for (int i = 1; i <= n; i++) cnt[c[i]]++;

	/*cout << "col: " << col << endl;

	for (int i = 0; i < col; i++) cout << cnt[i] << " ";
	cout << endl; */

	set<int> s;

	for (int i = 0; i < col; i++) s.insert(i);

	int m;
	cin >> m;

	for (int i = 1; i <= m; i++) {

		int a, b;
		cin >> a >> b;
		if (c[a] != c[b]) { continue;  }

		else { if(s.count(c[a])) s.erase(s.find(c[a])); }

	}

	if ((int)s.size() == 0) { return cout << 0 << endl, 0;  }

	int mx = 0;

	for (auto t : s) mx = max(mx, cnt[t]);

	cout << mx << endl;

	return  0;
}


#include <bits/stdc++.h>
const int maxn=100005;
using namespace std;
struct line
{
    int fr,to,ne;
}e[maxn<<1];
int he[maxn],pos[maxn],have[maxn],no[maxn],cnt,elem;
bool vis[maxn];
void addside(int u,int v)
{
    e[cnt].fr=u;  e[cnt].to=v;
    e[cnt].ne=he[u];
    he[u]=cnt++;
}
void dfs(int u)
{
    vis[u]=1;
    pos[u]=elem;
    have[elem]++;
    for(int x=he[u];x!=-1;x=e[x].ne)
    if(!vis[e[x].to])dfs(e[x].to);
}
int main()
{
    int n,m,a,b,ans=0;
    cin>>n>>m;
    memset(he,-1,sizeof(he));
    while(m--)
    {
        scanf("%d%d",&a,&b);
        a--;b--;
        addside(a,b);
        addside(b,a);
    }
    for(int i=0;i<n;i++)  if (!vis[i]) dfs(i),elem ++;
    cin>>m;
    while(m--)
    {
        scanf("%d%d",&a,&b);
        a--;b--;
        if(pos[a]==pos[b])no[pos[a]]=1;
    }
    for(int i=0;i<elem;i++)
    if(!no[i])ans=max(ans,have[i]);
    cout<<ans<<endl;
    return 0;
}


#include <iostream>
#include <vector>
using namespace std;

struct node : vector<int>
{
  int color, sz;
  node(): color(0), sz(0){}
};

int dfs(node*nodes, int act, int c)
{
  nodes[act].sz = 1;
  nodes[act].color = c;
  for(int i=0; i<nodes[act].size(); i++)
   if(nodes[nodes[act][i]].color != c)
    nodes[act].sz += dfs(nodes, nodes[act][i], c);
  return nodes[act].sz;
}

int main()
{
  int N, M;
  cin>>N>>M;
  node nodes[N+1];
  bool colors[N+1];

  for(int i=0, a, b; i<M; i++)
  {
    cin>>a>>b;
    nodes[a].push_back(b);
    nodes[b].push_back(a);
  }

  for(int i=1; i<=N; i++) //trovo dimensioni componenti senza archi rossi
  {
    colors[i] = true;
    if(nodes[i].color == 0)
     dfs(nodes, i, i);
  }

  cin>>M;
  for(int i=0,a,b; i<M; i++)
  {
    cin>>a>>b;
    if(nodes[a].color == nodes[b].color) //arco rosso tra due nodi dello stesso colore -> rende la componente non pi� utilizzabile
     colors[nodes[a].color] = false;
  }

  int mx = 0;
  for(int i=1; i<=N; i++)
   if(colors[nodes[i].color])
    mx = max(mx, nodes[i].sz);
  cout<<mx;
  return 0;
}


#include <iostream>
#include <vector>
#define u first
#define like second
using namespace std;

struct node : vector<pair<int, bool>>
{
  int color;
  node(): color(0){}
};

int dfs(node*nodes, int act, int c)
{
  int answ = 1;
  nodes[act].color = c;
  for(int i=0; i<nodes[act].size(); i++)
   if(!nodes[act][i].like)
   {
     if(nodes[nodes[act][i].u].color == c)
      return 0;
     nodes[nodes[act][i].u].color = -c;
   }
   else
    if(nodes[nodes[act][i].u].color != c)
    {
      if(nodes[nodes[act][i].u].color == -c) return 0;
      int r = dfs(nodes, nodes[act][i].u, c);
      if(r == 0) return 0;
      answ += r;
    }
  return answ;
}

int main()
{
  int N, M;
  cin>>N>>M;
  node nodes[N+1];

  for(int i=0, a, b; i<M; i++)
  {
    cin>>a>>b;
    nodes[a].push_back(make_pair(b, true));
    nodes[b].push_back(make_pair(a, true));
  }

  cin>>M;
  for(int i=0, a, b; i<M; i++)
  {
    cin>>a>>b;
    nodes[a].push_back(make_pair(b, false));
    nodes[b].push_back(make_pair(a, false));
  }

  int mx = 0;
  for(int i=1; i<=N; i++)
  {
    int sol = dfs(nodes, i, i);
    if(sol > mx)
     mx = sol;
  }
  cout<<mx;
  return 0;
}


#include <bits/stdc++.h>
#define N 2011

using namespace std;

int n, k, m;
int adj[N][N], V[N];

/* ------- DSU ------- */
int P[N], R[N];

int findP(int x) {
    if(P[x] == x) return x;
    return P[x] = findP(P[x]);
}

void join(int a, int b) {
    a = findP(a);
    b = findP(b);
    if(a != b) {
        if(R[b] > R[a]) swap(a,b);
        P[b] = a;
        R[a] += R[b];
        R[b] = R[a];
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    memset(V, true, sizeof V);
    cin >> n;
    for(int i=0; i<n; i++) {
        P[i] = i;
        R[i] = 1;
    }
    cin >> k;
    while(k--) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        join(u,v);
    }
    cin >> m;
    while(m--) {
        int u, v;
        cin >> u >> v;
        u--; v--;
        adj[u][v] = adj[v][u] = 1;
    }
    for(int i=0; i<n; i++) {
        int a = findP(i);
        for(int j=0; j<n; j++) {
            int b = findP(j);
            if(a == b && adj[i][j]) V[a] = false;
        }
    }
    int ans = 0;
    for(int i=0; i<n; i++) {
        int r = findP(i);
        if(V[r] && R[r] > ans) ans = R[r];
    }
    cout << ans << endl;
    return 0;
}


#include <iostream>
#include <sstream>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <tuple>
#include <unordered_set>

using namespace std;

int n, k, m;
vector<int> v[100000];
vector<int> v1[100000];
queue<int> q;
bool b[100000];
int ans = 0;
bool used[100000];
bool used1[100000];
bool t = true;
int sum = 0;

void bfs(int i) {
	q.push(i);
	for (int g = 0; g < (int)v1[i].size(); g++) {
		int h = v1[i][g];
		b[h] = true;
		if (used[h]) {
			t = false;
		}
	}
	while (!q.empty()) {
		int a = q.front();
		q.pop();
		used1[a] = true;
		used[a] = true;
		sum++;
		for (int j = 0; j < (int)v[a].size(); j++) {
			int x = v[a][j];
			if (b[x]) {
				t = false;
			}
			if (!used[x]) {
				used[x] = true;
				q.push(x);
				for (int g = 0; g < (int)v1[x].size(); g++) {
					int h = v1[x][g];
					b[h] = true;
					if (used[h]) {
						t = false;
					}
				}
			}
		}
	}
}

int main() {
	cin >> n >> k;
	for (int i = 0; i < k; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		a--;
		b--;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	cin >> m;
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		a--;
		b--;
		v1[a].push_back(b);
		v1[b].push_back(a);
	}
	for (int i = 0; i < n; i++) {
		if (used1[i]) {
			continue;
		}
		memset(used, 0, sizeof(used));
		memset(b, 0, sizeof(b));
		sum = 0;
		t = true;
		bfs(i);
		if (t) {
			ans = max(ans, sum);
		//	cout << sum << ' ' << i + 1 << endl;
		}
	}
	cout << ans << endl;
    return 0;
}


#include <iostream>
#include <sstream>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <tuple>
#include <unordered_set>

using namespace std;

int n, k, m;
vector<int> v[100000];
vector<int> v1[100000];
queue<int> q;
bool b[100000];
int ans = 0;
bool used[100000];
bool used1[100000];
bool t = true;
int sum = 0;

void bfs(int i) {
	q.push(i);
	for (int g = 0; g < (int)v1[i].size(); g++) {
		int h = v1[i][g];
		b[h] = true;
		if (used[h]) {
			t = false;
		}
	}
	while (!q.empty()) {
		int a = q.front();
		q.pop();
		used1[a] = true;
		used[a] = true;
		sum++;
		for (int j = 0; j < (int)v[a].size(); j++) {
			int x = v[a][j];
			if (b[x]) {
				t = false;
			}
			if (!used[x]) {
				used[x] = true;
				q.push(x);
				for (int g = 0; g < (int)v1[x].size(); g++) {
					int h = v1[x][g];
					b[h] = true;
					if (used[h]) {
						t = false;
					}
				}
			}
		}
	}
}

int main() {
	cin >> n >> k;
	for (int i = 0; i < k; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		v[a].push_back(b);
		v[b].push_back(a);
	}
	cin >> m;
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		v1[a].push_back(b);
		v1[b].push_back(a);
	}
	for (int i = 0; i < n; i++) {
		if (used1[i]) {
			continue;
		}
		memset(used, 0, sizeof(used));
		memset(b, 0, sizeof(b));
		sum = 0;
		bfs(i);
		if (t) {
			ans = max(ans, sum);
		//	cout << sum << ' ' << i + 1 << endl;
		}
	}
	cout << ans << endl;
    return 0;
}


#include <iostream>
#include <sstream>
#include <algorithm>
#include <unordered_map>
#include <vector>
#include <cstdio>
#include <cmath>
#include <string.h>
#include <cstring>
#include <map>
#include <set>
#include <queue>
#include <tuple>
#include <unordered_set>

using namespace std;

int n, k, m;
vector<int> v[100000];
vector<int> v1[100000];
queue<int> q;
bool b[100000];
int ans = 0;
bool used[100000];
bool used1[100000];
bool t = true;
int sum = 0;

void bfs(int i) {
	q.push(i);
	for (int g = 0; g < (int)v1[i].size(); g++) {
		int h = v1[i][g];
		b[h] = true;
		if (used[h]) {
			t = false;
		}
	}
	while (!q.empty()) {
		int a = q.front();
		q.pop();
		used1[a] = true;
		used[a] = true;
		sum++;
		for (int j = 0; j < (int)v[a].size(); j++) {
			int x = v[a][j];
			if (b[x]) {
				t = false;
			}
			if (!used[x]) {
				used[x] = true;
				q.push(x);
				for (int g = 0; g < (int)v1[x].size(); g++) {
					int h = v1[x][g];
					b[h] = true;
					if (used[h]) {
						t = false;
					}
				}
			}
		}
	}
}

int main() {
	cin >> n >> k;
	for (int i = 0; i < k; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		a--;
		b--;
		v[a].push_back(b);
		v[b].push_back(a);
	}
	cin >> m;
	for (int i = 0; i < m; i++) {
		int a, b;
		scanf("%d %d", &a, &b);
		a--;
		b--;
		v1[a].push_back(b);
		v1[b].push_back(a);
	}
	for (int i = 0; i < n; i++) {
		if (used1[i]) {
			continue;
		}
		memset(used, 0, sizeof(used));
		memset(b, 0, sizeof(b));
		sum = 0;
		bfs(i);
		if (t) {
			ans = max(ans, sum);
		//	cout << sum << ' ' << i + 1 << endl;
		}
	}
	cout << ans << endl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define BeatMeScanf ios_base::sync_with_stdio(false)
#define ll long long
#define nl "\n"
#define PI 3.14159265358979323846
#define sz 1000005
#define mod 1000000007
#define toint(a) atoll(a.c_str())
string tostr(int n) {stringstream rr;rr<<n;return rr.str();}
ll power(ll a,ll b){return b==0?:a*power(a,b-1);}
ll gcd(ll a,ll b) {return b==0? a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*(b/gcd(a,b));}
#define MX 2200

int par[MX];
int Size[MX];

void initializeSet(int n){
    for(int i=1;i<=n;i++){
        par[i]=i;
        Size[i]=1;
    }
}
int Find(int x){
    if(x!=par[x]) return par[x]=Find(par[x]);
    else return x;
}
void Union(int a,int b){
    int i=Find(a),j=Find(b);
    if(i==j) return;
    if(Size[i]>Size[j]) swap(i,j);
    par[i]=j;
    Size[j]+=Size[i];
}

int main()
{
    BeatMeScanf;
    int n,m,x,y;
    while(cin>>n>>m){
        initializeSet(n);
        for(int i=1;i<=m;i++){
            int a,b;
            cin>>a>>b;
            Union(a,b);
        }
        cin>>m;
        int dislike[MX];
        for(int i=0;i<2100;i++) dislike[i]=0;
        for(int i=1;i<=m;i++){
            int a,b,x,y;
            cin>>a>>b;

            if(Find(a)==Find(b))
                dislike[Find(a)]=1;
        }
        int mx=0;
        for(int i=1;i<=n;i++)
            if(dislike[Find(i)]!=1)
                mx=max(mx,Size[Find(i)]);

        cout<<mx<<nl;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define BeatMeScanf ios::sync_with_stdio(0)
#define ll long long
#define ull unsigned ll
#define CaseNum cout<<"Case "<<++no<<": "
#define nl "\n"
#define PI 3.14159265358979323846
#define sz 2020
#define mod 1000000007
#define toint(a) atoll(a.c_str())
string tostr(int n) {stringstream rr;rr<<n;return rr.str();}
ll power(ll a,ll b){return b==0?:a*power(a,b-1);}
ll gcd(ll a,ll b) {return b==0? a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*(b/gcd(a,b));}

///st.max_load_factor(0.25); st.reserve(512);

vector<int>graph[sz];
bool vis[sz];
int dislike[sz];
int mp[sz];

int bfs(int s,int mx){
    bool ok=true;
    vis[s]=1;
    queue<int>q;
    vector<int>vec;
    vec.clear();
    vec.push_back(s);
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();

        for(int i=0;i<graph[u].size();i++){
            int v=graph[u][i];
            if(vis[v]==0){
                vec.push_back(v);
                vis[v]=1;
                q.push(v);
            }
        }
    }
    for(int i=0;i<=2010;i++) mp[i]=0;
    int len=vec.size();
    for(int i=0;i<vec.size();i++)
        mp[dislike[vec[i]]]++;
    for(int i=2;i<=2010;i++){
        if(mp[i]>1){
            ok=false;
            break;
        }
    }
    if(ok) mx=max(mx,len);
    return mx;
}

int main(){
    BeatMeScanf;
    int n,k;
    while(cin>>n>>k){
        int c=2,m,mx=0;
        for(int i=0;i<=n;i++) graph[i].clear();
        for(int i=1;i<=k;i++){
            int a,b;
            cin>>a>>b;
            graph[a].push_back(b);
            graph[b].push_back(a);
        }
        cin>>m;
        for(int i=0;i<=2010;i++) dislike[i]=0;
        for(int i=1;i<=m;i++){
            int a,b;
            cin>>a>>b;
            if(dislike[a]==0) dislike[a]=c;
            if(dislike[b]==0) dislike[b]=c;
            c++;
        }

        for(int i=0;i<=2010;i++) vis[i]=0;
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                mx=bfs(i,mx);
            }
        }
       cout<<mx<<nl;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define BeatMeScanf ios::sync_with_stdio(0)
#define ll long long
#define ull unsigned ll
#define CaseNum cout<<"Case "<<++no<<": "
#define nl "\n"
#define PI 3.14159265358979323846
#define sz 20000
#define mod 1000000007
#define toint(a) atoll(a.c_str())
string tostr(int n) {stringstream rr;rr<<n;return rr.str();}
ll power(ll a,ll b){return b==0?:a*power(a,b-1);}
ll gcd(ll a,ll b) {return b==0? a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*(b/gcd(a,b));}

///st.max_load_factor(0.25); st.reserve(512);

vector<int>graph[sz];
set<int>st[sz];
set<int>::iterator it;
bool vis[sz];

int bfs(int s,int mx){
    bool ok=true;
    vis[s]=1;
    queue<int>q;
    vector<int>vec;
    vec.clear();
    vec.push_back(s);
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();

        for(int i=0;i<graph[u].size();i++){
            int v=graph[u][i];
            if(vis[v]==0){
                vec.push_back(v);
                vis[v]=1;
                q.push(v);
            }
        }
    }
    int i,len=vec.size();
    for(i=0;i<vec.size();i++){
        for(int j=i+1;j<vec.size();j++){
            if((st[vec[i]].find(vec[j])) != (st[vec[i]].end())){
                ok=false;
                break;
            }
        }
        if(!ok) break;
    }
    if(i==len) mx=max(mx,len);
    return mx;
}

int main(){
    BeatMeScanf;
    int n,k;
    cin>>n>>k;
    int m,mx=0;
    for(int i=0;i<=n;i++) graph[i].clear();
    for(int i=1;i<=k;i++){
        int a,b;
        cin>>a>>b;
        graph[a].push_back(b);
        graph[b].push_back(a);
    }
    cin>>m;

    for(int i=1;i<=m;i++){
        int a,b;
        cin>>a>>b;
        st[a].insert(b);
        st[b].insert(a);
    }

    for(int i=0;i<=2010;i++) vis[i]=0;
    for(int i=1;i<=n;i++){
        if(!vis[i]){
            mx=bfs(i,mx);
        }
    }
    cout<<mx<<nl;
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define BeatMeScanf ios::sync_with_stdio(0)
#define ll long long
#define ull unsigned ll
#define CaseNum cout<<"Case "<<++no<<": "
#define nl "\n"
#define PI 3.14159265358979323846
#define sz 200000
#define mod 1000000007
#define toint(a) atoll(a.c_str())
string tostr(int n) {stringstream rr;rr<<n;return rr.str();}
ll power(ll a,ll b){return b==0?:a*power(a,b-1);}
ll gcd(ll a,ll b) {return b==0? a:gcd(b,a%b);}
ll lcm(ll a,ll b) {return a*(b/gcd(a,b));}

///st.max_load_factor(0.25); st.reserve(512);

vector<int>graph[sz];
bool vis[sz];
int dislike[sz];
int mp[sz];

int bfs(int s,int mx){
    bool ok=true;
    vis[s]=1;
    queue<int>q;
    vector<int>vec;
    vec.clear();
    vec.push_back(s);
    q.push(s);
    while(!q.empty()){
        int u=q.front();
        q.pop();

        for(int i=0;i<graph[u].size();i++){
            int v=graph[u][i];
            if(vis[v]==0){
                vec.push_back(v);
                vis[v]=1;
                q.push(v);
            }
        }
    }
    for(int i=0;i<=2010;i++) mp[i]=0;
    int len=vec.size();
    for(int i=0;i<vec.size();i++)
        mp[dislike[vec[i]]]++;
    for(int i=2;i<=2010;i++){
        if(mp[i]>1){
            ok=false;
            break;
        }
    }
    if(ok) mx=max(mx,len);
    return mx;
}

int main(){
    BeatMeScanf;
    int n,k;
    while(cin>>n>>k){
        int c=2,m,mx=0;
        for(int i=0;i<=n;i++) graph[i].clear();
        for(int i=1;i<=k;i++){
            int a,b;
            cin>>a>>b;
            graph[a].push_back(b);
            graph[b].push_back(a);
        }
        cin>>m;
        for(int i=0;i<=2010;i++) dislike[i]=0;
        for(int i=1;i<=m;i++){
            int a,b;
            cin>>a>>b;
            if(dislike[a]==0) dislike[a]=c;
            if(dislike[b]==0) dislike[b]=c;
            c++;
        }

        for(int i=0;i<=2010;i++) vis[i]=0;
        for(int i=1;i<=n;i++){
            if(!vis[i]){
                mx=bfs(i,mx);
            }
        }
       cout<<mx<<nl;
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int,int> ii;

int main() {
	cin.tie(0); cout.tie(0); ios_base::sync_with_stdio(0);
	int n; cin>>n;
	int k; cin>>k;
	int u,v;
	map<int,vector<int>> adj;
	for (int i=0; i<k; i++) {
		cin>>u>>v; u--; v--;
		adj[u].push_back(v);
		adj[v].push_back(u);
	}
	int m; cin>>m;
	set<ii> st;
	for (int i=0; i<m; i++) {
		cin>>u>>v; u--; v--;
		st.insert({u,v});
		st.insert({v,u});
	}

	int ret=0;
	set<int> vis;
	for (int i=0; i<n; i++) {
		if(vis.find(i)==vis.end()) {
			vis.insert(i);
			vector<int> group;
			queue<int> q; q.push(i);
			while(!q.empty()) {
				int cur=q.front(); q.pop();
				group.push_back(cur);
				for (auto nxt : adj[cur]) {
					if(vis.find(nxt)==vis.end())
						vis.insert(nxt), q.push(nxt);
				}
			}
			bool ok=true;
			for (auto u : group)
				for (auto v : group)
					if(st.find({u,v})!=st.end()) {
						ok=false;
						break;
					}
			if(ok) ret=max(ret,(int) group.size());
		}
	}
	cout << ret << endl;
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
long long int par[2010];
long long int r[2010];
long long int e[2010];
long long int c[2010];
int find_par(int x)
{
	if(par[x]==x)
	return x;
	return par[x]=find_par(par[x]);
}
void union_set(int x,int y)
{
	if(r[x]>r[y])
	par[y]=x;
	if(r[x]<r[y])
	par[x]=y;
	if(r[x]==r[y])
	{
		r[x]=r[x]+1;
		par[y]=x;
	}
}
int main()
{
	long long int x,y,x1,y1,i,n,k;
	cin>>n;
	for(i=1;i<=n;i++)
	{
		par[i]=i;
		r[i]=0;
		e[i]=0;
		c[i]=0;
	}
	cin>>k;
	for(i=0;i<k;i++)
	{
		cin>>x>>y;
		x1=find_par(x);
		y1=find_par(y);
		if(x1!=y1)
		{
			union_set(x1,y1);
		}
	}
	cin>>k;
	for(i=0;i<k;i++)
	{
		cin>>x>>y;
		x1=find_par(x);
		y1=find_par(y);
		if(x1==y1)
		{
			e[x1]=1;
		}
	}
	for(i=1;i<=n;i++)
	{
		x=find_par(i);
		c[x]=c[x]+1;
	}
	long long int ans=0;
	for(i=1;i<=n;i++)
    {
    	if((par[i]==i)&&(e[i]==0))
    	ans=max(ans,c[i]);
	}
	cout<<ans<<endl;
}


#include<bits/stdc++.h>
using namespace std;
int pre[100010],s[100010];
int find(int x)
{
	int r=x;
	while(pre[r]!=r)
		r=pre[r];
	int i=x,j;
	while(i!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}
int main()
{
	int n,i,a,b,fa,fb,t,max,m,p;
	scanf("%d%d",&m,&n);
	for(i=1;i<=100000;i++)
	{
		pre[i]=i;
		s[i]=1;
	}
	for(i=0;i<n;i++)
	{
		scanf("%d %d",&a,&b);
		fa=find(a);
		fb=find(b);
		if(fa!=fb)
		{
			pre[fa]=fb;
			s[fb]+=s[fa];
		}
	}
	scanf("%d",&p);
	for(i=0;i<p;i++)
	{
		scanf("%d %d",&a,&b);
		fa=find(a);
		fb=find(b);
		if(fa==fb)
			s[fb]=0;
	}
	for(t=0,i=1;i<=m;i++)
	{
		//cout<<"#"<<s[i]<<endl;
		if(t<s[i]&&s[find(i)]!=0)
			t=s[i];
	}
	printf("%d\n",t);
	return 0;
}


//Be Name Khoda
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef long double ld;
const int MOD = (int)1e9 + 7;
const int MAXN = (int)2e5 + 7;
const int MAX_MAT = (int)2e3 + 7;
const ll inf = (ll)1e18;
const int infint = (int)2e9;
vector<int> G[MAX_MAT];
bool visited[MAXN];
vector<int> comps[MAX_MAT];
int Can[MAX_MAT][MAX_MAT];
int cur_comp = -1;
void dfs(int u)
{
	visited[u] = true;
	comps[cur_comp].push_back(u);
	for (int i = 0; i < G[u].size(); i++)
	{
		int v = G[u][i];
		if(!visited[v])
			dfs(v);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	int n, k, m;
	cin >> n >> k;
	for (int i = 0; i < k; i++)
	{
		int u, v;
		cin >> u >> v;
		G[u].push_back(v);
		G[v].push_back(u);
	}
	fill(visited, visited + MAXN, false);
	for (int i = 1; i <= n; i++)
	{
		if(!visited[i])
		{
			cur_comp++;
			dfs(i);
		}
	}
	cin >> m;
	for (int i = 0; i < m; i++)
	{
		int u, v;
		cin >> u >> v;
		Can[u][v] = 1;
		Can[v][u] = 1;
	}
	int ans = 0;
	for (int i = 0; i <= cur_comp; i++)
	{
		bool T = false;
		for (int j = 0; j < comps[i].size(); j++)
			for (int j1 = j + 1; j1 < comps[i].size(); j1++)
			{
				int u = comps[i][j], v = comps[i][j1];
				if(Can[u][v])
					T = true;
			}
		if(!T)
			ans = max(ans, (int)comps[i].size());
	}
	cout << ans;
}


#include<bits/stdc++.h>

using namespace std;

const int MAXN = 5000;
int p[MAXN], size[MAXN], n, m;

int find_set( int v )
{
	return v == p[v] ? v : p[v] = find_set( p[v] );
}
void union_set( int x, int y )
{
	x = find_set( x );
	y = find_set( y );
	if( x != y ){
		if( size[x] < size[y] ) swap( x, y );
		p[x] = y;
		size[y] += size[x];
	}
}
int main()
{
        cin >> n >> m;
        for( int i = 1; i <= n; i++ ) size[i] = 1, p[i] = i;
        while( m-- ){
        	int x, y;
        	cin >> x >> y;
        	union_set( x, y );
        }
        int mx = 0;
        cin >> m;
        while( m-- ){
        	int x, y;
        	cin >> x >> y;
        	if( find_set( x ) == find_set( y ) )
        		size[find_set( x )] = 0;
        }
        for( int i = 1; i <= n; i++ ){
        	mx = max( mx, size[find_set( i )] );
        }
        cout << mx << endl;
}


#include <bits/stdc++.h>
#define int long long
using namespace std;

bool isPowerOfTwo (int x)
{
  return x && (!(x&(x-1)));
}

int power(int x, unsigned int y)
{
    int res = 1;
    while (y > 0) {
        if (y & 1)
            res = res * x;
        y = y >> 1;
        x = x * x;
    }
    return res;
}

const int Nmax = 2002;
vector<int> adj[Nmax];
vector<int> adj1[Nmax];
int color[Nmax];
bool v[Nmax];

bool ok = true;
int cnt = 0;
set<int> st;
void dfs(int u)
{
    v[u] = true;
    st.insert(u);
    cnt++;
    for(int nxt: adj[u])
    {
        if(!v[nxt])
            dfs(nxt);
    }
    for(int nxt: adj1[u])
    {
        if(st.count(nxt))
            ok =false;
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

	int n, k;
	cin >> n >> k;
    for(int i = 0; i < k; ++i)
    {
        int x, y;
        cin >> x >> y;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    int m;
    cin >> m;
    for(int i = 0; i < m; ++i)
    {
        int x, y;
        cin >> x >> y;
        adj1[x].push_back(y);
        adj1[y].push_back(x);
    }
    int ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        if(!v[i])
        {
            ok =true;
            st.clear();
            cnt = 0;
            dfs(i);
            if(ok)
                ans = max(ans, cnt);
        }
    }
    cout << ans << "\n";
    return 0;
}


#include <bits/stdc++.h>
#define int long long
using namespace std;

bool isPowerOfTwo (int x)
{
  return x && (!(x&(x-1)));
}

int power(int x, unsigned int y)
{
    int res = 1;
    while (y > 0) {
        if (y & 1)
            res = res * x;
        y = y >> 1;
        x = x * x;
    }
    return res;
}

const int Nmax = 2002;
vector<int> adj[Nmax];
vector<int> adj1[Nmax];
int color[Nmax];
bool v[Nmax];

bool no[Nmax][Nmax];
bool yes[Nmax][Nmax];

int c = 1;
void dfs1(int u)
{
    v[u] = true;
    color[u] = c;
    for(int nxt: adj1[u])
    {
        if(!v[nxt])
            dfs1(nxt);
    }
}

set<int> st;
int cnt = 0;
void dfs(int u)
{
    v[u] = true;
    cnt++;
    st.insert(color[u]);
    for(int nxt: adj[u])
    {
        if(!v[nxt])
            dfs(nxt);
    }
}

signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);

	int n, k;
	cin >> n >> k;
	for(int i = 1; i <= n; ++i)
    {
        for(int j = 1; j <= n; ++j)
            no[i][j] = yes[i][j] = 0;
    }
    for(int i = 0; i < k; ++i)
    {
        int x, y;
        cin >> x >> y;
        adj[x].push_back(y);
        adj[y].push_back(x);
    }
    int m;
    cin >> m;
    for(int i = 0; i < m; ++i)
    {
        int x, y;
        cin >> x >> y;
        adj1[x].push_back(y);
        adj1[y].push_back(x);
    }
    for(int i = 1; i <= n; ++i)
    {
        if(!v[i])
        {
            dfs1(i);
            c++;
        }
    }
    for(int i = 1; i <= n; ++i)
        v[i] =false;
    int ans = 0;
    for(int i = 1; i <= n; ++i)
    {
        if(!v[i])
        {
            st.clear();
            cnt = 0;
            dfs(i);
            if(cnt == st.size())
                ans = max(ans, (int)st.size());
        }
    }
    cout << ans << "\n";
    return 0;
}


#include <bits/stdc++.h>
#include <iostream>
#define pb push_back
#define mp make_pair
#define F first
#define S second
#define all(x) (x).begin(), (x).end()
#define rep(i, n) for(int i = 0; i < n; ++i)
#define repr(i,n) for(int i = n - 1; i >= 0; --i)
#define Rep(i, a, n) for(int i = (a); i <=(n); ++i)
#define Repr(i, a, n) for(int i = (n); i >= (a); --i)
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const int inf = int(2e9);
const int _inf = -inf;
const int mod = inf + 7;
using namespace std;
bool bad[2002][2002];
vector<int> g[2002];
bool used[2002];
queue<int> q;
int cnt;
vector<int> res;
void bfs(int v){
	used[v] = 1;
	cnt++;
	res.pb(v);
	rep(i, g[v].size()){
		int to = g[v][i];
		if(!used[to] && !bad[v][to]){
			bfs(to);
		}
	}
}
void solve(){
	int n, k;
	cin >> n >> k;
	for(int i = 0; i < k; ++i)
	{
		int u, v;
		cin >> u >> v;
		g[u].pb(v);
		g[v].pb(u);
	}
	int m;
	cin >> m;

	for(int i = 0; i < m; ++i){
		int u, v;
		cin >> u >> v;
		bad[u][v] = 1;
		bad[v][u] = 1;
	}
	int mx = 0;
	for(int i = 1; i <= n; ++i){
		if(!used[i]) {
			cnt = 0;
			res.clear();
			bfs(i);
			bool flag = 1;
			for(int j = 0; j < res.size(); ++j){
				for(int k = j + 1; k < res.size(); ++k){
					if(bad[res[j]][res[k]]) flag = 0;
				}
			}
			if(flag)
			mx = max(mx, (int)res.size());
		}
	}
	cout << mx;
}
int main(){

	solve();
return 0;
}


//
//  main.cpp
//  C2. Party
//
//  Created by Yousef on 11.08.20.
//

#include <iostream>
#include <vector>
#include <set>
#include <algorithm>
#include <utility>

using namespace std;

int id = 0;
vector<vector<int>> adj;
vector<pair<int , int>> h;
vector<bool> visited;
vector <set<int>> groups;

void dfs(int n)
{
        for(auto k: adj[n])
        {
            if(!visited[k])
            {
                visited[k] = 1;
                groups[id].insert(k);
                dfs(k);
            }
        }

}

int main(int argc, const char * argv[]) {
    ios::sync_with_stdio(0); cin.tie(0);

    int n, k, m, u, v, size = 0;

    cin>>n>>k;

    adj = vector<vector<int>> (n + 1);
    visited = vector <bool> (n + 1);
    groups = vector<set<int>> (n + 1);

    for(int i =0; i < k; i++)
    {
        cin>>u>>v;
        adj[u].push_back(v);
        adj[v].push_back(u);

    }

    cin>>m;
    h = vector <pair<int,int>>();

    for(int i = 1; i<=m; i++)
    {
        cin>>u>>v;
        h.push_back(make_pair(u,v));

    }

    for(int i = 1; i <= n; i++)
    {
        if(!visited[i])
        {
            id ++;
            groups[id].insert(i);
            visited[i] = 1;
            dfs(i);
        }
    }

    for(int i = 1; i < groups.size(); i++)
    {
        bool f = true;
        for(auto m: h)
        {
            if(groups[i].count(m.first) == 1 && groups[i].count(m.second) == 1)
                {
                    f = false;
                    groups.erase(groups.begin() + i);
                    i--;
                    break;
                }
        }
    }

    for(auto k: groups)

    {
        size = max(size, int(k.size()));
    }
    cout<<size;

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int N = 2000002;
#define ll long long int

//Implementation of DSU
int parent[N], sz[N];
int findSet(int i) {
    if(parent[i] == i)
        return i;
    return parent[i] = findSet(parent[i]);
}
bool isSameSet(int i, int j) {
    return findSet(i) == findSet(j);
}
void makeEdge(int i, int j) {
    if(isSameSet(i, j))
        return;
    i = parent[i], j = parent[j];
    if(sz[i] < sz[j]) {
        parent[i] = parent[j];
        sz[j] += sz[i];
        sz[i] = 0;
    } else {
        parent[j] = parent[i];
        sz[i] += sz[j];
        sz[j] = 0;
    }
}

int main() {
#ifndef ONLINE_JUDGE
    freopen("/home/riham/ClionProjects/Problems/input.txt", "r", stdin);
//    freopen("/home/riham/ClionProjects/Problems/output.txt", "w", stdout);
#endif // ONLINE_JUDGE
    int n, k, m;
    int f, t;
    scanf("%d%d", &n, &k);
    for(int i=0;i<n;i++) {
        parent[i] = i;
        sz[i] = 1;
    }
    for(int i=0;i<k;i++) {
        scanf("%d%d", &f, &t);
        makeEdge(f-1, t-1);
    }
    vector<pair<int, int> >later;
    scanf("%d", &m);
    for(int i=0;i<m;i++) {
        scanf("%d%d", &f, &t);
        f = findSet(f-1), t = findSet(t-1);
        if(f == t) {
            sz[f] = 0;
        }
        else later.push_back({f, t});
    }
    for(int i=0;i< later.size();i++) {
        if(sz[later[i].first] < sz[later[i].second])
            sz[later[i].first] = 0;
    }
    printf("%d", *max_element(sz, sz+n));
    return 0;
}