原题链接
#include <iostream>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int N = 20009;
const int M = 150000;
int h[M], ne[M], to[M], idx;
int dfn[N], low[N], times;
int instk[N], stk[N], top;
int sz[N], id[N], scc_cnt;
void add(int u, int v) {ne[idx] = h[u], to[idx] = v, h[u] = idx++;}
int f;
void tarjan(int u) {
dfn[u] = low[u] = ++ times;
stk[++top] = u;
instk[u] = 1;
int cnt = 0;
for (int i = h[u]; i != -1; i = ne[i]) {
int v = to[i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
} else if (instk[v]) {
low[u] = min(low[u], dfn[v]);
}
if (!instk[u])f = 1;//没有横插边,设想一下,一条边伸到了一个不在当前强连通分量的地方。
if (low[v] > dfn[u]) {
f = 1;//如果自己儿子的边回不来,那么必然就是一个桥,直接通向别处
}
if (dfn[v] < dfn[u]) cnt++;//首先是儿子的向上碰到自己祖先的数量
}
if (cnt > 1) {
f = 1;
}
if (low[u] == dfn[u]) {
scc_cnt++;
int v = stk[top];
do{
v = stk[top];
top--;
instk[v] = 0;
sz[scc_cnt] ++;
id[v] = scc_cnt;
} while (v != u);
}
}
void solve() {
times = top = idx = scc_cnt = f = 0;
memset(h, -1, sizeof h);
memset(dfn, 0, sizeof dfn);
memset(sz, 0, sizeof sz);
int n;cin >> n;
int u, v;
while (cin >> u >> v) {
if( u == 0 && v == 0)break;
add(u, v);
}
for (int i = 0; i < n; i ++) {
if (!dfn[i])tarjan(i);
}
if (scc_cnt == 1 && !f) cout << "YES
";
else cout << "NO
";
}
int main() {
int t = 1;cin >> t;
while (t--)solve();
return 0;
}