当前位置:   article > 正文

无向图求三元环的个数

无向图求三元环

原文链接

它实际上是想始终保证复杂度为m×根号m,也就是保证枚举的边数尽可能小于根号m。所以判断一下,小于根号m直接可以进行下一个点的枚举就像dfs深搜一样,如果大了,我们不继续,而是从最初点上枚举别的就像bfs广搜一样

代码:

  1. /*
  2. * 无向图求三元环
  3. */
  4. #include<cstdio>
  5. #include<vector>
  6. #include<unordered_set>
  7. #include<cmath>
  8. using namespace std;
  9. typedef long long ll;
  10. const int maxn=1e5+10;
  11. vector<int> g[maxn];
  12. unordered_set<ll> st;
  13. int vis[maxn],link[maxn],out[maxn];
  14. int main(){
  15. ll ans,sum;
  16. int n,m,x,y,z,B;
  17. while(scanf("%d%d",&n,&m)!=EOF){
  18. B=sqrt(m);
  19. st.clear();
  20. for(int i=1;i<=n;i++){
  21. g[i].clear();
  22. vis[i]=link[i]=out[i]=0;
  23. }
  24. for(int i=1;i<=m;i++){
  25. scanf("%d%d",&x,&y);
  26. g[x].push_back(y);
  27. out[x]++;
  28. g[y].push_back(x);
  29. out[y]++;
  30. st.insert((ll)n*x+y); //对于大于根号下m的边不好这样进行判断时候有边相连,速度快而且更加家简便
  31. st.insert((ll)n*y+x);
  32. }
  33. ans=0;
  34. for(int i=1;i<=n;i++){
  35. x=i;
  36. vis[x]=1;
  37. for(int j=0;j<g[x].size();j++){
  38. link[g[x][j]]=x;
  39. }
  40. for(int j=0;j<g[x].size();j++){
  41. sum=0;
  42. y=g[x][j]; //枚举第二个点,第一条边
  43. if(vis[y]) continue;
  44. if(out[y]<=B){
  45. for(int k=0;k<g[y].size();k++){
  46. z=g[y][k];
  47. if(link[z]==x) sum++;
  48. }
  49. }else{
  50. for(int k=0;k<g[x].size();k++){
  51. z=g[x][k];
  52. if(st.find((ll)z*n+y)!=st.end()) sum++;
  53. }
  54. }
  55. ans+=sum;
  56. }
  57. }
  58. printf("%lld\n",ans/3);
  59. }
  60. return 0;
  61. }

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/64600
推荐阅读
相关标签
  

闽ICP备14008679号