题意大概是这样的
给出n个二元组(xi,yi) 要求我们选定三个二元组 满足以下条件:
1.三组的xi互不相同
2.三组的yi互不相同
答案是求有多少种方案满足以上的一个或者多个条件。
用到的思想和高中排列组合的知识比较像,因为正着考虑每一种合法的情况比较复杂,种类也比较多,所以我们可以倒过来考虑,求出每一个不合法的方案,再用总方案数减去不合法的方案数就可以了
具体思路:
想要不合法的话,上面的两个条件,有一个不满足的就可以了
现在我们随机取一对数字,假设xi为a,yi为b,现在我们已经有b这一种了,第二个,我们可以在剩下的yi为b的数对里,随意挑换一个数队,也就是cnt[b]-1,现在我们的第二个数字已经挑好了,第三个数字也是同理,只不过考虑的是a,在剩下的yi为b的数对里,随意挑选一个数对,也就是cnt[a]-1;
答案的公式就是这样了,我们只需要在一开始的时候,开3个容器记录特们出现的次数就可以了
代码
#include <bits/stdc++.h>
#define int long long
#define gcd __gcd
#define endl '\n'
#define mem(x, y) memset(x, y, sizeof(x))
#define inf 0x3f3f3f
#define ninf 0xc0c0c0c0
#define FAST ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
using namespace std;
typedef pair<int, int> PII;
const int N = 200010;
void solve()
{
map<int, int> m1, m2;
map<int, vector<int>> m3;
int n;
cin >> n;
for (int i = 0; i < n; i++)
{
int x, y;
cin >> x >> y;
m1[x]++, m2[y]++;
m3[y].push_back(x);
}
int ans = 0;
for (int i = 0; i < m3.size(); i++)
{
int tmp = 0;
for (auto it : m3[i])
{
tmp += m1[it] - 1;
}
ans += tmp * (m2[i] - 1);
}
cout << n * (n - 1) * (n - 2) / 6 - ans << endl;
}
signed main()
{
FAST;
int t;
cin >> t;
while (t--)
solve();
}