# NYOJ 16 矩形嵌套（动态规划 or 贪心）

#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int N = 104;
int arr[N][N], dp[N][N];
int main()
{
int n, t;
cin >> t ;
while (t -- ) {
cin >> n;
memset(arr , 0, sizeof(arr));
memset(dp , 0, sizeof(dp));
int a, b;
for (int i = 0; i < n; i ++) {
cin >> a >> b;
arr[a][b] ++;
arr[b][a] ++;
}
int maxx = 0;
for(int i = 1; i < N; i ++) {
for (int j = 1; j < N; j ++) {
dp[i][j] = max(dp[i - 1][j], dp[i][j - 1]);
if(arr[i - 1][j - 1])
dp[i][j] = max(dp[i][j] , dp[i - 1][j - 1] + 1);
}
}
cout << dp[N - 1][N - 1] << endl;
}
}
/*
4
1 1
1 2
2 1
3 2
*/


#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
struct Node
{
int length, width;
}rectangle[1005];
bool cmp(const Node &a, const Node &b)
{
if(a.length != b.length)
return a.length < b.length;
else
return a.width < b.width;
}
bool judge(const Node &a, const Node &b)
{
if(b.length  > a.length && b.width > a.width || b.length > a.width && b.width > a.length)return true;
else return false;
}
int main()
{
int t, n, dp[1005];
cin >> t ;
while ( t -- ) {
cin >> n ;
for (int i = 0; i < n; i ++) {
cin >> rectangle[i].length >> rectangle[i].width ;
if(rectangle[i].length < rectangle[i].width)
swap(rectangle[i].length , rectangle[i].width);
}
sort(rectangle , rectangle + n, cmp);
int ans = 0;
for (int i = 0; i < n; i ++) {//枚举起点
// Node temp = rectangle[i];
dp[i] = 1;
for(int j = 0; j < i; j ++) {//初始和结束的边界很重要 慢慢体会吧
if(judge(rectangle[j] , rectangle[i])) {
dp[i] = max(dp[i], dp[j] + 1);
}
}
ans = max(ans , dp[i]);
}
cout << ans << endl;
}
}