【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; }
继续考虑优化,我们切换枚举顺序,从度数最大的点开始枚举。 每次枚举完毕以后,删去度数最大的点和它连接的所有边,然后重复这个过程,也能统计出答案。
时间复杂度证明:
代码待补