解题报告:luogu P6057
题目链接:P6057 [加油武汉]七步洗手法
为武汉助威!
大佬:真·小学奥数
我:?怎么算啊?
\(ps\):本来想切个绿题就滚去写文化课,结果......憋了好长时间。
总算刚了出来,开始误入枚举白边的黑洞(这个字有锅吧?!)出不来了。
主要思路:
\[ans=C_{n}^3-\text{不同色的三元环数}=\dfrac{n(n-1)(n-2)}{6}-\text{不同色的三元环数}
\]
那么不同色的三元环数咋算呢,我们发现可以枚每个点,记录其发出的不同色边对数,最后累加会发现每个三元环都记录了两次,除一下即可,对于一个点发出的黑白边数读入白边时从黑边里减即可。
为什么正确呢,我们发现不同色的三元环只有两种情况:
白白黑,黑黑白。
这样其三个顶点有两个具有不同的边对,即统计了两次。
记得开\(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\n",sum-now/2);
return 0;
}