Monocarp is the coach of the Berland State University programming teams. He decided to compose a problemset for a training session for his teams.

Monocarp has n problems that none of his students have seen yet. The i-th problem has a topic a_i (an integer from 1 to n) and a difficulty b_i (an integer from 1 to n). All problems are different, that is, there are no two tasks that have the same topic and difficulty at the same time.

Monocarp decided to select exactly 3 problems from n problems for the problemset. The problems should satisfy at least one of two conditions (possibly, both):

  * the topics of all three selected problems are different; 
  * the difficulties of all three selected problems are different. 



Your task is to determine the number of ways to select three problems for the problemset.

Input

The first line contains a single integer t (1 ≤ t ≤ 50000) — the number of testcases.

The first line of each testcase contains an integer n (3 ≤ n ≤ 2 ⋅ 10^5) — the number of problems that Monocarp have.

In the i-th of the following n lines, there are two integers a_i and b_i (1 ≤ a_i, b_i ≤ n) — the topic and the difficulty of the i-th problem.

It is guaranteed that there are no two problems that have the same topic and difficulty at the same time.

The sum of n over all testcases doesn't exceed 2 ⋅ 10^5.

Output

Print the number of ways to select three training problems that meet either of the requirements described in the statement.

Example

Input


2
4
2 4
3 4
2 1
1 3
5
1 5
2 4
3 3
4 2
5 1


Output


3
10

Note

In the first example, you can take the following sets of three problems:

  * problems 1, 2, 4; 
  * problems 1, 3, 4; 
  * problems 2, 3, 4. 



Thus, the number of ways is equal to three.
// Problem: D. Training Session
// Contest: Codeforces - Educational Codeforces Round 115 (Rated for Div. 2)
// URL: https://codeforces.com/contest/1598/problem/D
// Memory Limit: 256 MB
// Time Limit: 2000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

import java.io.*;
import java.util.*;
import java.math.*;
import static java.lang.Math.max;
import static java.lang.Math.min;
import static java.lang.Math.abs;


/**
 * zxz 
 * problem link:
 **/
public class Main {
    //put some data here

    /**
     * do some clean action before next testcase
     */
    private void clear() {

    }
	long [] dp = new long[200001];

    private void solve() throws Exception {
        rf();
        int n = readInt();
        // int m = readInt();
        ArrayList<ArrayList<Integer>> list = new ArrayList<>(n + 1);
        for(int i = 0; i <= n; i++){
        	list.add(new ArrayList<Integer>());
        }
        int [] cnt = new int[n + 1];
        for(int i = 0; i < n; i++){
        	rf();
        	int a = readInt();
        	int b = readInt();
        	list.get(a).add(b);
        	cnt[b]++;
        }
        long ans = (long)n * (n - 1) * (n - 2) / 6;
        for(int i = 1; i <= n; i++){
        	int t = list.get(i).size();
        	if(t >= 2){
        		t -= 1;
        		for(int to : list.get(i)){
        			ans -= (long)(cnt[to] - 1) * t;
        		}
        	}
        }
        addAns(ans);

    }

    private void run() throws Exception {
		dp[3] = 1;
		dp[4] = 4;
		BigInteger big = new BigInteger(4 + "");
		for(int i = 5; i <= 200000; i++){
			big = big.multiply(new BigInteger(i + "")).divide(new BigInteger((i - 3) + ""));
			dp[i] = big.longValue();
			// if(i == 200000){
				// addAns(dp[i]);
			// }
		}
       rf();
       int T = readInt();
        // int T = 1;

        while (T-- > 0) {
            solve();
            if (T != 0) {
                clear();
            }
        }
        printAns();
    }

    public static void main(String[] args) throws Exception {
        new Main().run();
    }

    StringBuilder sb = new StringBuilder();
    BufferedReader infile = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st;

	private void addAns(int a){
		sb.append(a + "\n");
	}
	
	private void addAns(long a){
		sb.append(a + "\n");
	}
	
	private void addAns(String s){
		sb.append(s + "\n");
	}

    private void rf() throws IOException {
        st = new StringTokenizer(infile.readLine());
    }

    private int readInt() {
        return Integer.parseInt(st.nextToken());
    }

    private long readLong() {
        return Long.parseLong(st.nextToken());
    }


    private void printAns() {
        System.out.println(sb);
    }

    private int[] readArr(int N) throws Exception {
        int[] arr = new int[N];
        rf();
        for (int i = 0; i < N; i++) {
            arr[i] = Integer.parseInt(st.nextToken());
        }
        return arr;
    }

    private void print(int[] arr) {
        //for debugging only
        for (int x : arr) {
            System.out.print(x + " ");
        }
        System.out.println();
    }

    private long[] readArr2(int N) throws Exception {
        long[] arr = new long[N];
        st = new StringTokenizer(infile.readLine());
        for (int i = 0; i < N; i++) {
            arr[i] = Long.parseLong(st.nextToken());
        }
        return arr;
    }

    private boolean isPrime(long n) {
        if (n < 2) {
            return false;
        }
        if (n == 2 || n == 3) {
            return true;
        }
        if (n % 2 == 0 || n % 3 == 0) {
            return false;
        }
        long sqrtN = (long) Math.sqrt(n) + 1;
        for (long i = 6L; i <= sqrtN; i += 6) {
            if (n % (i - 1) == 0 || n % (i + 1) == 0) {
                return false;
            }
        }
        return true;
    }

    private long gcd(long a, long b) {
        if (a > b) {
            a = (a + b) - (b = a);
        }
        if (a == 0L) {
            return b;
        }
        return gcd(b % a, a);
    }
    
    private double pow(double x, long N) {
        double ans = 1.0;
        // 贡献的初始值为 x
        double x_contribute = x;
        // 在对 N 进行二进制拆分的同时计算答案
        while (N > 0) {
            if (N % 2 == 1) {
                // 如果 N 二进制表示的最低位为 1，那么需要计入贡献
                ans *= x_contribute;
            }
            // 将贡献不断地平方
            x_contribute *= x_contribute;
            // 舍弃 N 二进制表示的最低位，这样我们每次只要判断最低位即可
            N /= 2;
        }
        return ans;
    }
    
    long pow_mod(long x, long i, long mod){
	    if(i == 0){
	        return 1;
	    }
	    long temp = pow_mod(x, i >> 1, mod);
	    temp = temp * temp % mod;
	    if((i & 1 )!= 0){
	        temp = temp * x % mod;
	    }
	    return temp;
	}
    

}
