无向图三/四元环计数
都是
三元环
我们首先给每条边定向,规定:对于原图中的每条边,若
然后所有的三元环一定会长这个样子:(蒯了个图,如果不能显示请扒源代码或者移步cnblogs)
我们可以按照
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
struct node{
int v,next;
}edge[200010];
int n,m,t,ans,head[100010],u[200010],v[200010],d[100010],vis[100010];
void add(int u,int v){
edge[++t].v=v;edge[t].next=head[u];head[u]=t;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&u[i],&v[i]);
d[u[i]]++;d[v[i]]++;//度数
}
for(int i=1;i<=m;i++){
if(d[u[i]]>d[v[i]]||(d[u[i]]==d[v[i]]&&u[i]>v[i]))swap(u[i],v[i]);
add(u[i],v[i]);//定向
}
for(int x=1;x<=n;x++){
for(int i=head[x];i;i=edge[i].next)vis[edge[i].v]=x;//标记
for(int i=head[x];i;i=edge[i].next){
for(int j=head[edge[i].v];j;j=edge[j].next){
if(vis[edge[j].v]==x)ans++;//爆扫
}
}
}
printf("%d\n",ans);
return 0;
}
四元环
同样给每条边定向,原则和上面一样。
然后四元环会变成这个样子:
双向边表示两个方向都可以。
我们每次只要从度最大的点出发,枚举出点的出点,每次枚举到一个点就把答案加上那个点的计数器,同时那个点的计数器
void find(){
for(int x=1;x<=n;x++){
for(int i=head[x];i;i=edge[i].next){
for(int j=head[edge[i].v];j;j=edge[j].next){
if(d[x]<d[edge[j].v]||(d[x]==d[edge[j].v]&&x<edge[j].v)){
ans+=cnt[edge[j].v];cnt[edge[j].v]++;
}
}
}
for(int i=head[x];i;i=edge[i].next){
for(int j=head[edge[i].v];j;j=edge[j].next){
cnt[edge[j].v]=0;
}
}
}
}
然后是复杂度证明:可以证明这样定向的时候每个点的出度都是不超过
考虑两种情况:
- 原图度数不超过
,显然出度不超过 。 - 原图度数超过
,此时由于整张图的度数是 的,因此最多只有 个节点度数不小于它,因此只能连 条出边。
所以把所有节点扫一遍是
快踩
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)