#include <bits/stdc++.h>
using namespace std;
#define int long long
#define double long double
#define DEBUG 1
#ifdef DEBUG
#define OUT(x) cerr << (#x) << '=' << (x) << endl
#define OUT2(c) cerr << (#c) << " = {"; for (auto it = (c).begin(); it != (c).end(); ++it) cerr << (it == (c).begin() ? "" : ", ") << *it; cerr << "}" << endl;
#else
#define OUT(x)
#define OUT2(c)
#endif
const int MAXN = 1005;
int n, m, q;
/*
* Standard DSU: Path Compression + Union by Size.
* Time: O(alpha(N)) per operation (nearly constant).
* Use this UNLESS you need rollbacks.
*/
struct DSU {
vector<int> p, sz;
int num_sets;
DSU(int n) {
p.resize(n + 1);
iota(p.begin(), p.end(), 0);
sz.assign(n + 1, 1);
num_sets = n;
}
int find(int x) {
// Path compression: flattens the tree structure
return (p[x] == x) ? x : (p[x] = find(p[x]));
}
bool unite(int a, int b) {
int x = find(a), y = find(b);
if (x == y) return false;
// Union by size: attach smaller to larger
if (sz[x] < sz[y]) swap(x, y);
p[y] = x;
sz[x] += sz[y];
num_sets--;
return true;
}
bool same(int a, int b) { return find(a) == find(b); }
int size(int x) { return sz[find(x)]; }
int count() { return num_sets; }
};
void solve() {
cin >> n >> m >> q;
DSU dsu(n + 5);
for(int i = 0; i < m; i++){
for(int to = 1; to <= n; to++){
int frm; cin >> frm;
dsu.unite(frm, to);
}
}
for(int i = 0; i < q; i++){
int a, b; cin >> a >> b;
cout << (dsu.same(a, b) ? "DA" : "NE") << "\n";
}
}
signed main() {
ios_base::sync_with_stdio(0);
cin.tie(0);
int tt; tt = 1;
while (tt--) {
solve();
}
}