There are n employees working in company "X" (let's number them from 1 to n for convenience). Initially the employees didn't have any relationships among each other. On each of m next days one of the following events took place:

  * either employee y became the boss of employee x (at that, employee x didn't have a boss before); 
  * or employee x gets a packet of documents and signs them; then he gives the packet to his boss. The boss signs the documents and gives them to his boss and so on (the last person to sign the documents sends them to the archive); 
  * or comes a request of type "determine whether employee x signs certain documents". 



Your task is to write a program that will, given the events, answer the queries of the described type. At that, it is guaranteed that throughout the whole working time the company didn't have cyclic dependencies.

Input

The first line contains two integers n and m (1 ≤ n, m ≤ 105) — the number of employees and the number of events. 

Each of the next m lines contains the description of one event (the events are given in the chronological order). The first number of the line determines the type of event t (1 ≤ t ≤ 3). 

  * If t = 1, then next follow two integers x and y (1 ≤ x, y ≤ n) — numbers of the company employees. It is guaranteed that employee x doesn't have the boss currently. 
  * If t = 2, then next follow integer x (1 ≤ x ≤ n) — the number of the employee who got a document packet. 
  * If t = 3, then next follow two integers x and i (1 ≤ x ≤ n; 1 ≤ i ≤ [number of packets that have already been given]) — the employee and the number of the document packet for which you need to find out information. The document packets are numbered started from 1 in the chronological order. 



It is guaranteed that the input has at least one query of the third type.

Output

For each query of the third type print "YES" if the employee signed the document package and "NO" otherwise. Print all the words without the quotes.

Examples

Input

4 9
1 4 3
2 4
3 3 1
1 2 3
2 2
3 1 2
1 3 1
2 2
3 1 3


Output

YES
NO
YES
import static java.lang.Integer.*;
import static java.lang.Math.*;
import static java.util.Arrays.*;

import java.util.*;

public class E {

	class Node {
		Node(int j) { this.j = j; }
		public String toString() { return "" + j; };

		Node [] P = new Node[20]; int K = -1, j;

		Node find (int q) {
			if (q < 0) return null;
			if (q == 0) return this;
			if (q == 1) return P[0];
			if (bitCount(q) == 1) {
				int n = numberOfTrailingZeros(q);
				if (P[n] != null)
					return P[n];
				else {
					find(q/2);
					if (P[n-1] != null) {
						if ((P[n] = P[n-1].find(q/2)) != null)
							K = max(K, n);
						return P[n];
					}
					else
						return null;
				}
			}
			int t = lowestOneBit(q), s = q - t;
			Node Y = find(t);
			if (Y != null)
				return Y.find(s);
			else
				return null;
		}

		int level() {
			if (K < 0)
				return 0;

			for (int i = K+1; P[i-1] != null; ++i)
				find(1 << i);

			Node m = P[K];
			return (1 << K) + m.level();
		}

		void connect(Node m) {
			P[K = 0] = m;
		}
	}

	public E () {
		int N = sc.nextInt(), M = sc.nextInt();
		int [][] B = sc.nextInts(M);

		Node [] Z = new Node[N];
		for (int i : rep(N))
			Z[i] = new Node(i);

		int c = 0;
		PriorityQueue<int []> Q = new PriorityQueue<>(10, new Comparator<int[]>() {
			public int compare(int[] a, int[] b) {
				return a[0] - b[0];
			}
		});
		for (int i : rep(M))
			if (B[i][0] == 3) {
				int n = --B[i][2], x = --B[i][1];
				Q.add(new int [] { n, x, c++ });
			}

		String [] res = new String [c];
		fill(res, "NO");

		int n = -1;
		for (int i : rep(M)) {
			int t = B[i][0];
			switch(t) {
			case 1:
				int x = --B[i][1], y = --B[i][2];
				Z[x].connect(Z[y]);
				break;
			case 2:
				x = --B[i][1]; ++n;
				while (!Q.isEmpty() && Q.peek()[0] == n) {
					int [] q = Q.poll();
					y = q[1]; int s = q[2];
					int U = Z[x].level(), V = Z[y].level();
					if (Z[x].find(U-V) == Z[y])
						res[s] = "YES";
				}
				break;
			case 3:
				break;
			}
		}

		println(res);
	}

	private static int [] rep(int N) { return rep(0, N); }
	private static int [] rep(int S, int T) { if (T <= S) return new int [0]; int [] res = new int [T-S]; for (int i = S; i < T; ++i) res[i-S] = i; return res; }
	////////////////////////////////////////////////////////////////////////////////////
	private final static IOUtils.MyScanner sc = new IOUtils.MyScanner();
	private static void println (Object o) { IOUtils.println(o); }
	private static class IOUtils {
		public static class MyScanner {
			public String next() { newLine(); return line[index++]; }
			public int nextInt() { return Integer.parseInt(next()); }
			public String nextLine() { line = null; return readLine(); }
			public String [] nextStrings() { return split(nextLine()); }
			public int [] nextInts() {
				String [] L = nextStrings();
				int [] res = new int [L.length];
				for (int i = 0; i < L.length; ++i)
					res[i] = Integer.parseInt(L[i]);
				return res;
			}
			public int [][] nextInts (int N) {
				int [][] res = new int [N][];
				for (int i = 0; i < N; ++i)
					res[i] = nextInts();
				return res;
			}
			//////////////////////////////////////////////
			private boolean eol() { return index == line.length; }
			private String readLine() {
				try {
					return r.readLine();
				} catch (Exception e) {
					throw new Error (e);
				}
			}
			private final java.io.BufferedReader r;
			private MyScanner () { this(new java.io.BufferedReader(new java.io.InputStreamReader(System.in))); }
			private MyScanner (java.io.BufferedReader r) {
				try {
					this.r = r;
					while (!r.ready())
						Thread.sleep(1);
					start();
				} catch (Exception e) {
					throw new Error(e);
				}
			}
			private String [] line;
			private int index;
			private void newLine() {
				if (line == null || eol()) {
					line = split(readLine());
					index = 0;
				}
			}
			private String [] split(String s) { return s.length() > 0 ? s.split(" ") : new String [0]; }
		}
		private static String build(Object o, Object ... A) { return buildDelim(" ", o, A); }
		private static String buildDelim(String delim, Object o, Object ... A) {
			StringBuilder b = new StringBuilder();
			append(b, o, delim);
			for (Object p : A)
				append(b, p, delim);
			return b.substring(delim.length());
		}
		//////////////////////////////////////////////////////////////////////////////////
		private static void start() { if (t == 0) t = millis(); }
		private static void append(StringBuilder b, Object o, String delim) {
			if (o.getClass().isArray()) {
				int len = java.lang.reflect.Array.getLength(o);
				for (int i = 0; i < len; ++i)
					append(b, java.lang.reflect.Array.get(o, i), delim);
			} else if (o instanceof Iterable<?>)
				for (Object p : (Iterable<?>) o)
					append(b, p, delim);
			else {
				if (o instanceof Double)
					o = new java.text.DecimalFormat("#.############").format(o);
				b.append(delim).append(o);
			}
		}
		private static java.io.PrintWriter pw = new java.io.PrintWriter(System.out);
		private static void print(Object o, Object ... A) { pw.println(build(o, A)); }
		private static void println(Object o) {
			if (o.getClass().isArray()) {
				int len = java.lang.reflect.Array.getLength(o);
				for (int i = 0; i < len; ++i)
					print(java.lang.reflect.Array.get(o, i));
			} else if (o instanceof Iterable<?>)
				for (Object p : (Iterable<?>) o)
					print(p);
			else
				print(o);
		}
		private static void err(Object o, Object ... A) { System.err.println(build(o, A)); }
		private static void exit() {
			IOUtils.pw.close();
			System.out.flush();
			err("------------------");
			err(IOUtils.time());
			System.exit(0);
		}
		private static long t;
		private static long millis() { return System.currentTimeMillis(); }
		private static String time() { return "Time: " + (millis() - t) / 1000.0; }
	}
	public static void main (String[] args) { new E(); IOUtils.exit(); }
}
