(2021牛客多校三)J-Counting Triangles(思维)

该博客主要介绍了一道算法题,题目要求在给定的完全图中找出由三条权值相同的边组成的三角形数量。通过反向思考,计算出所有三角形的总数,然后减去不满足条件的三角形个数(即边权不完全相同的三角形)。博主提供了C++代码实现,并展示了如何避免重复计数以得到正确答案。
摘要由CSDN通过智能技术生成

样例输入: 

10 114514

样例输出:

35

题意:给定一个n个点的完全图,每条边的权值可能为0,也可能为1,让我们找出由三条权值相同的边组成的三角形的个数,每条边的边权是通过随机数给的。

这道题是通过反向思考来解决的,有n个点,由于是一个完全图,所以任意三个点都能够组成一个三角形,那么所有三角形的总个数就是C(n,3)=n*(n-1)*(n-2)/6

现在我们只要找出来边权不完全相同的三角形的个数即可,我们拿一个权值分别为0,0,1的三角形来举例:

我们先来枚举以A的两条边组成的三角形中权值不完全相同的三角形的个数,那么我们可以任意选一条以A作为起始点的权值为0的边以及选一条以A作为起始点的权值为1的边,那么如果这两条边都参与组成三角形的话一定不能组成一个三个权值完全相同的三角形,那么我们只需要记录从A出发权值为0的边数cnt,由于是一个完全图,那么从A出发的边一共有n-1条,那么从A出发权值为1的边一共有n-1-cnt个,所以这样的三角形一共有cnt*(n-cnt-1)个三角形,但是对于这个三角形而言,当我们遍历C点时也会记录一次,但是遍历B时就不会被记录,因为这个三角形中由B出发的两条边权都是0,所以对于每个不满足题意的三角形我们都会重复记录一次,所以不满足题意的三角形的总个数我们最后需要除以2,再用图中总的三角形个数-不满足题意的三角形的个数即可得到答案。

下面是代码:

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<vector>
using namespace std;
const int N=8e3+10;
namespace GenHelper
{
    unsigned z1,z2,z3,z4,b,u;
    unsigned get()
    {
        b=((z1<<6)^z1)>>13;
        z1=((z1&4294967294U)<<18)^b;
        b=((z2<<2)^z2)>>27;
        z2=((z2&4294967288U)<<2)^b;
        b=((z3<<13)^z3)>>21;
        z3=((z3&4294967280U)<<7)^b;
        b=((z4<<3)^z4)>>12;
        z4=((z4&4294967168U)<<13)^b;
        return (z1^z2^z3^z4);
    }
    bool read() {
      while (!u) u = get();
      bool res = u & 1;
      u >>= 1; return res;
    }
    void srand(int x)
    {
        z1=x;
        z2=(~x)^0x233333333U;
        z3=x^0x1234598766U;
        z4=(~x)+51;
      	u = 0;
    }
}
using namespace GenHelper;
bool edge[8005][8005];
vector<int>p[N];
int main() {
  	int n, seed;
  	cin >> n >> seed;
  	srand(seed);
  	long long sum=0;
  	for (int i = 0; i < n; i++)
    	for (int j = i + 1; j < n; j++)
        	edge[j][i] = edge[i][j] = read();
	for(int i=0;i<n;i++)
	{
		long long cnt=0;
		for(int j=0;j<n;j++)
			if(edge[i][j]) cnt++;
		sum+=cnt*(n-1-cnt);
	}
	long long ans=(long long)n*(n-1)/2*(n-2)/3;
    cout<<ans-sum/2;
 	return 0;
}
//10 114514

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值