すのはら荘春原庄的雪

无向图三/四元环计数小记

vectorwyx·2022-01-10 15:40·181 次阅读

无向图三/四元环计数小记

三元环计数

先把无向图里的点按度数定序(如果度数相等可以按照编号比较),把每条无向边变为由序更小的点连向序更大的点。

这样做的好处在于,建出的新图是一张 DAG 且每个点的出度是 O(m) 级别的,我们可以方便地枚举。具体地,我们枚举每个三元环中度数最小的那个点,然后接着枚举它的所有出边以及出边的出边,在枚举的过程中更新答案。代码如下:

Copy
//author:望远星 #include<bits/stdc++.h> #define pii pair<int,int> #define fi first #define se second #define pb push_back #define mk make_pair #define sml(x,y) (x=min(x,y)) #define big(x,y) (x=max(x,y)) #define ll long long #define ull unsigned long long #define db double #define fo(i,x,y) for(int i=x;i<=y;++i) #define go(i,x,y) for(int i=x;i>=y;--i) using namespace std; inline int read(){int x=0,fh=1; char ch=getchar(); while(!isdigit(ch)){if(ch=='-') fh=-1; ch=getchar();} while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0'; ch=getchar();} return x*fh;} inline void out(int *a,int l,int r){fo(i,l,r) cout<<*(a+i)<<' ';puts("");} const int N=1e5+5; vector<int> e[N]; pii ed[N<<1]; int n,m,deg[N],vis[N],ti; signed main(){ cin>>n>>m; fo(i,1,m){ int x=read(),y=read(); deg[x]++,deg[y]++; ed[i]=mk(x,y); } fo(i,1,m){ if(deg[ed[i].fi]>deg[ed[i].se]||(deg[ed[i].fi]==deg[ed[i].se]&&ed[i].fi>ed[i].se)) swap(ed[i].fi,ed[i].se); e[ed[i].fi].pb(ed[i].se); }int ans=0; fo(i,1,n){ ++ti; for(int j:e[i]) vis[j]=ti; for(int j:e[i]) for(int k:e[j]) ans+=vis[k]==ti; } cout<<ans; return 0; }

例题:CF985G,以及自己的题解 https://www.luogu.com.cn/blog/dream-of-Au/solution-cf985g

四元环计数

和三元环计数类似,还是先定序然后建出 DAG。不同的是为了保证复杂度和正确性,我们在枚举时要先枚举与一个点相连的所有无向边,然后再枚举这些无向边连出的有向边。

posted @   真正的菜鸡vectorwyx  阅读(181)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示