带 思 维 题
【题目描述】
刚刚上高中的洁洁在学习组合数学的过程中遇到一道麻烦的题目,她希望你能帮助她解决。给定一张无向完全图 (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
", a - 2 * b);
return 0;
}