60.同色三角形 (15分)
C时间限制:3000 毫秒 | C内存限制:3000 Kb
题目内容:
平面上有n个点(n≤8000),每两个点之间都有一条红色或者是黑色的线段,任意三点均不共线。
现在,已知哪些点之间连的线段是红色的,剩下的线段都是黑色的,要求计算这些点组成的三角
形中有多少是同色的(顶点编号从1到n)?
输入描述
第一行是n, m(3≤n≤8000),n表示点的个数,m表示红色线段的条数。下面m行,每
一行都是两个整数a和b,表示点a和点b之间的线段是红色的(a<b)。
输出描述
只有一行,表示同色三角形的个数。
提示:本题输出数据可能会超出长整数(long int)的范围。
输入样例
6 5
1 2
1 3
2 3
2 5
3 6
思路:
这道题应该反着想,但是我就看着题目同色三角形,于是就想如何查找同色,自己傻了,同色三角形的个数 = 总三角形的个数 - 异色三角形的个数
总三角形的个数就是在n各点中取3个点,就是n*(n-1)*(n-2)/(1*2*3)
异色三角形就是先固定一个点m(for循环遍历每个点)然后vector中v[m]中存储了与点m相邻的点,然后n-v[m]-1存储的是与m点不相邻的点,
于是就可以求了。
代码:
#include<iostream> #include<stdio.h> #include<vector> using namespace std; typedef long long ll; const int maxn = 8e3+10; ll sum = 0; vector<int> v[maxn]; int main(){ int n,m; cin>>n>>m; int a,b; for(int i=1;i<=m;i++){ scanf("%d%d",&a,&b); v[a].push_back(b); v[b].push_back(a); } for(int i=1;i<=n;i++){ sum+=(v[i].size()*(n-v[i].size()-1)); } cout<<n*(n-1)*(n-2)/6-sum/2<<endl;//sum/2是因为是一条边加一个点组成三角形,而边中的两个点是重复算了两次的,所以要/2
return 0; }