#include <fstream>
#include <iostream>
#include <vector>
#include <bitset>
#include <string.h>
#include <algorithm>
#include <iomanip>
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <set>
#include <map>
#include <string>
#include <queue>
#include <deque>
using namespace std;
const char infile[] = "gossips.in";
const char outfile[] = "gossips.out";
///ifstream fin(infile);
ofstream fout(outfile);
const int MAXN = 100005;
const int oo = 0x3f3f3f3f;
typedef vector<int> Graph[MAXN];
typedef vector<int> :: iterator It;
const inline int min(const int &a, const int &b) { if( a > b ) return b; return a; }
const inline int max(const int &a, const int &b) { if( a < b ) return b; return a; }
const inline void Get_min(int &a, const int b) { if( a > b ) a = b; }
const inline void Get_max(int &a, const int b) { if( a < b ) a = b; }
char parse[1 << 15];
int pos;
Graph G;
int N, M, Q, K, out[MAXN], in[MAXN];
set <int> S[MAXN << 3], T[MAXN << 3];
bool Ans;
bitset <MAXN> notRoot;
class Scanner {
public:
Scanner(string file, int buffer_size = 32768):
buffer_size_(buffer_size) {
file_ = fopen(file.c_str(), "r");
buffer_ = new char[buffer_size];
pointer_ = buffer_ + buffer_size_;
}
Scanner& operator>>(int &object) {
object = 0;
while (next() < '0' or next() > '9')
advance();
while (next() >= '0' and next() <= '9') {
object = object * 10 + next() - '0';
advance();
}
return *this;
}
private:
char next() {
if (pointer_ == buffer_ + buffer_size_) {
pointer_ = buffer_;
fread(buffer_, 1, buffer_size_, file_);
}
return *pointer_;
}
void advance() {
++pointer_;
}
FILE *file_;
int buffer_size_;
char *buffer_, *pointer_;
};
Scanner fin(infile);
/*
inline int get() {
int number = 0;
while(!(isdigit(parse[pos])))
if(++ pos == 1 << 15) {
fin.getline(parse, 1 << 15, '\0');
pos = 0;
}
while(isdigit(parse[pos])) {
number = number * 10 + parse[pos] - '0';
if(++ pos == 1 << 15) {
fin.getline(parse, 1 << 15, '\0');
pos = 0;
}
}
return number;
}*/
//#define parse
inline void DFs(int Node) {
in[Node] = ++ K;
for(It it = G[Node].begin(), fin = G[Node].end(); it != fin ; ++ it)
DFs(*it);
out[Node] = ++ K;
}
inline void Update(int Node, int st, int dr, int a, int b, int c) {
T[Node].insert(c);
if(a <= st && dr <= b) {
S[Node].insert(c);
return;
}
int mid = ((st + dr) >> 1);
if(a <= mid)
Update(Node << 1, st, mid, a, b, c);
if(mid < b)
Update((Node << 1) | 1, mid+1, dr, a, b, c);
}
inline void Query(int Node, int st, int dr, int a, int b, int c, int d) {
set <int> :: iterator it = S[Node].lower_bound(c);
if(it != S[Node].end() && *it <= d) {
Ans = 1;
return;
}
if(st == dr || T[Node].lower_bound(c) == T[Node].end() || (*T[Node].lower_bound(c) > d))
return ;
int mid = ((st + dr) >> 1);
if(a <= mid)
Query(Node << 1, st, mid, a, b, c, d);
if(mid < b)
if(!Ans)
Query((Node << 1) | 1, mid+1, dr, a, b, c, d);
}
int main() {
#ifndef parse
fin >> N >> M >> Q;
#endif // parse
#ifdef parse
N = get();
M = get();
Q = get();
#endif
for(int i = 1 ; i <= M ; ++ i) {
int x, y;
#ifndef parse
fin >> x >> y;
#endif // parse
#ifdef parse
x = get();
y = get();
#endif
notRoot[y] = 1;
G[x].push_back(y);
}
for(int i = 1 ; i <= N ; ++ i)
if(!notRoot[i])
DFs(i);
for(int i = 1 ; i <= Q ; ++ i) {
int op, x, y;
#ifdef parse
op = get();
x = get();
y = get();
#endif
#ifndef parse
fin >> op >> x >> y;
#endif // parse
if(op == 1) {
Ans = false;
Query(1, 1, K, in[x], out[x], in[y], out[y]);
if(Ans)
fout << "YES\n";
else fout << "NO\n";
}
else
Update(1, 1, K, in[x], out[x], in[y]);
}
//fin.close();
fout.close();
return 0;
}