解题报告:luogu P6057

题目链接:P6057 [加油武汉]七步洗手法
为武汉助威!
大佬:真·小学奥数
我:?怎么算啊?
(ps):本来想切个绿题就滚去写文化课,结果......憋了好长时间。
总算刚了出来,开始误入枚举白边的黑洞(这个字有锅吧?!)出不来了。
主要思路:

[ans=C_{n}^3- ext{不同色的三元环数}=dfrac{n(n-1)(n-2)}{6}- ext{不同色的三元环数} ]

那么不同色的三元环数咋算呢,我们发现可以枚每个点,记录其发出的不同色边对数,最后累加会发现每个三元环都记录了两次,除一下即可,对于一个点发出的黑白边数读入白边时从黑边里减即可。
为什么正确呢,我们发现不同色的三元环只有两种情况:
白白黑,黑黑白。
这样其三个顶点有两个具有不同的边对,即统计了两次。
记得开(long;long)
这样时间复杂度是(O(n+m))的,可以通过本题。

(Code):

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int MAXN=100005;
int m,l,r;
ll n,sum=0,w[MAXN],b[MAXN],now=0;//black and white
int main()
{
	scanf("%lld%d",&n,&m);
	for(int i=1;i<=n;i++) b[i]=n-1,w[i]=0; 
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d",&l,&r);
		b[l]--,w[l]++;
		b[r]--,w[r]++;
	}
	sum=n*(n-1)*(n-2)/6;
	for(int i=1;i<=n;i++) now+=b[i]*w[i];
	printf("%lld
",sum-now/2);
	return 0;
} 
原文地址:https://www.cnblogs.com/tlx-blog/p/12488544.html