【2021noip模拟赛day3】C. 复杂问题

【题意】

给定n个点m条边的无向带点权简单图,统计这张图所有本质不同的四元环的权值之和,$mod 1e9+7$

【分析】

首先,我们考虑一个$O(n^2)$的做法

我们利用meet in the middle的思想,每次枚举两层即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+5;
int n,m;
int G[2005][2005];
ll val[maxn];
int xx[2005],yy[2005];
int main()
{
    freopen("fz.in","r",stdin);
    freopen("fz.out","w",stdout);
    scanf("%d%d",&n,&m);
    int x,y;
    for(int i=1;i<=n;i++) scanf("%d",&val[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        if(x>y) swap(x,y);
        xx[i]=x; yy[i]=y;
        G[x][y]=G[y][x]=1;
    }
    ll ans=0;
    for(int i=1;i<=m;i++)
        for(int j=1;j<=m;j++)
        {
            int a=xx[i],b=yy[i];
            int c=xx[j],d=yy[j];
            if(b<c && G[b][d] && G[a][c])
               ans=(ans+val[a]+val[b]+val[c]+val[d])%mod;
            if(b<c && G[b][c] && G[a][d])
                ans=(ans+val[a]+val[b]+val[c]+val[d])%mod;
            if(a<c && b>d && G[a][d] && G[b][c])
                ans=(ans+val[a]+val[b]+val[c]+val[d])%mod;
       }
    printf("%lld\n",ans);
    return 0;
}

继续考虑优化,我们切换枚举顺序,从度数最大的点开始枚举。 每次枚举完毕以后,删去度数最大的点和它连接的所有边,然后重复这个过程,也能统计出答案。

时间复杂度证明:

 

 

代码待补

posted @ 2021-09-19 23:36  andyc_03  阅读(38)  评论(0编辑  收藏  举报