CodeForces 51 E.Pentagon(组合数学)

Description

给出一个 n 个点m条边的无向图,问五元环个数

Input

第一行两整数 n,m 分别表示点数和边数,之后 m 行每行两个整数u,v表示 u,v 之间有一条无向边

(1n700,0mn(n1)2)

Output

输出五元环个数

Sample Input

5 5
1 2
2 3
3 4
4 5
5 1

Sample Output

1

Solution

假设一个五元环为 uabvcu ,可以看出该五元环是由 uv 的一条长度为 2 的路径和一条长度为3的路径组成,但是其中有一些不合法的,通过分析 u,v,a,b,c 中两两相同的情况可以看出,不合法的情况就是一个三元环从某个顶点出去一条边又回来,所以现在问题变成求任意两点之间长度为 2 3的路径数量以及求三元环配一条边的数量,第一个问题只需求出邻接矩阵 A 的平方B=A2和三次方 C=A3 ,那么 B[i][j] C[i][j] 就是 i j的长度为 2 3的路径数量,对于三元环,直接枚举 i,j,k ,两两相连则构成一个三元环,配一条边的时候要注意,比如在 i 点上多配一条边,由于五元环相邻两点不相同,故在i上可以配 deg[i]1 条边,进而一个三元环对非法五元环的贡献就是 deg[i]+deg[j]+deg[k]3

Code

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<set>
#include<ctime>
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const int INF=0x3f3f3f3f,maxn=705;
ll A[maxn][maxn],B[maxn][maxn],C[maxn][maxn];
int n,m,deg[maxn];
void Mul(ll A[][maxn],ll B[][maxn],ll C[][maxn])
{
    for(int i=1;i<=n;i++)
        for(int j=1;j<=i;j++)
        {
            C[i][j]=0;
            for(int k=1;k<=n;k++)C[i][j]+=A[i][k]*B[k][j];
            C[j][i]=C[i][j];
        }
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
        {
            deg[i]=0;
            for(int j=1;j<=n;j++)A[i][j]=0;
        }
        while(m--)
        {
            int u,v;
            scanf("%d%d",&u,&v);
            A[u][v]=A[v][u]=1;
            deg[u]++,deg[v]++;
        }
        Mul(A,A,B);
        Mul(A,B,C);
        ll ans=0;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                ans+=B[i][j]*C[i][j];
        ans/=10;
        for(int i=1;i<=n;i++)
            for(int j=i+1;j<=n;j++)
                if(A[i][j])
                    for(int k=j+1;k<=n;k++)
                        if(A[i][k]&&A[j][k])
                            ans-=(deg[i]+deg[j]+deg[k]-3);
        printf("%I64d\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值