数三角形

带 思 维 题

【题目描述】
刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决。给定一张无向完全图 \(G\),其中大部分边被染成蓝色,但也有一些边被染成红色或者绿色。现在,洁洁需要给这张图的多样性进行打分。一张图的多样性取决于它的同色和异色三角形的个数。具体来说,\(G\) 中每有一个三边颜色都互不同的三角形(异色三角形)可以得 \(3\) 分,每有一个三边颜色都相同的三角形(同色三角形)则要被扣掉 \(6\) 分,其它三角形不得分也不扣分。
现在,请你写一个程序来计算 \(G\) 的多样性分数。

【输入格式】
第一行两个正整数 \(n\)\(m\),其中 \(n\) 表示 \(G\) 中顶点的个数,\(m\) 表示 \(G\) 中红色或者绿色的边的条数。
接下来 \(m\) 行每行包括三个整数 \(a,b,c\),代表连接顶点 \(a\) 和顶点 \(b\) 的边颜色为红色 \((c=1)\) 或者绿色 \((c=2)\)

【输出格式】
一行,\(G\) 的多样性得分。

【数据范围】
\(n \le 100000, m \le min(\frac{n(n-1)}{2},200000)\)

也就是说 请你\(O(n)\)解决此题

下面来看看正解的思路:

\(a\)表示两条邻边颜色不相同的角的个数,\(b\)表示两条邻边颜色相同的角的个数。
三角形有三种,第一种是三边各不相同的,设数目为\(x\),第二种是三边全部相同的,设它为\(y\),剩下的都是两边相同,一边不同的,设它为\(z\)
每个\(x\)型三角形有\(3\)\(a\)型角,\(0\)\(b\)型角; 每个\(y\)型三角形有\(0\)\(a\)型角,\(3\)\(b\)型角; 每个\(z\)型三角形有\(2\)\(a\)型角,\(1\)\(b\)型角。
所以\(a=3x+2z, b=3y+z\)
而我们要求的正好是\(a-2b\),即\(a-2b=3x+2z-2*(3y-z)=3x-6y\)

\(a, b\)都是很好求的,组合数算一算
【代码实现】

#include <iostream>
#include <cstdio>
using namespace std;
typedef long long ll;

ll n, m, ans;
ll a, b;
ll num[100005][3];

int main() {
	scanf("%lld %lld", &n, &m);
	for (int i = 1; i <= m; i++) {
		ll x, y, z;
		scanf("%lld %lld %lld", &x, &y, &z);
		num[x][z]++; num[y][z]++;
	}
	for (int i = 1; i <= n; i++) {
		num[i][0] = n - 1 - num[i][1] - num[i][2];
		a = a + num[i][0] * num[i][1] + num[i][1] * num[i][2] + num[i][2] * num[i][0];
		b = b + (num[i][0] * (num[i][0] - 1) / 2) + (num[i][1] * (num[i][1] - 1) / 2) + (num[i][2] * (num[i][2] - 1) / 2);
	}
	printf("%lld\n", a - 2 * b);
	return 0;
}
posted @ 2019-08-26 10:22  AK_DREAM  阅读(289)  评论(0编辑  收藏  举报