组合数学 单色三角形,,(排列组合+容斥原理)
题目:空间里有n个点,任意三点不共线。每两个点之间都用红色或者黑色线段链接。如果
一个三角形的三条边同色,则这个三角形是单色三角形。对于给定的红色线段列表,
找出单色三角形的个数。
分析:由于三角形总数C(n,3),所以求出异色三角形个数就求出了同色三角形个数。用暴力
枚举的方法,我们将遍历所有的三角形,时间复杂度为O(n^3),则必定超时。而经过推敲,我们会
发现这样的对应关系,一个异色三角形存在两个顶点,在该三角形中与它们相邻的两边是不同色
的;而对从一个顶点出发的两条异色边都属于一个异色三角形。这是个一对二的关系。设第i个点
连接了ai条红边、n-1-ai条黑边,这些边一定属于ai(n-1-ai)个不同的异色三角形。由于异色三角形
都会被考虑两次,所以最终的答案为ans/2。这个思想只需要从第一个顶点遍历到最后一个顶点,
所以时间复杂度是O(n)。
1 #include<iostream> 2 #include<vector> 3 4 using namespace std; 5 const int maxn = 10000; 6 int n, m, T; 7 long long ans; 8 vector<int>s[maxn]; 9 int main() 10 { 11 ios::sync_with_stdio(false); 12 cin >> T; 13 while (T--) 14 { 15 s->clear(); 16 cin >> n >> m; 17 for (int i = 1; i <= m; i++) 18 { 19 int a, b; 20 cin >> a >> b; 21 s[a].push_back(b); 22 s[b].push_back(a); 23 } 24 for (int i = 1; i <= n; i++) 25 ans += (n - 1 - s[i].size())*s[i].size(); 26 ans /= 2; 27 cout << (n*(n - 1)*(n - 2)) / 6 - ans << endl; 28 } 29 return 0; 30 }