首页 > 其他分享 >无向图三元环 查找/计数

无向图三元环 查找/计数

时间:2022-09-07 11:33:22浏览次数:94  
标签:度数 int 复杂度 无向 sqrt 计数 查找 三元 size

理解

时间复杂度 \(O(M \sqrt{M})\)
作用
求出无向图的所有三元环

过程
首先要对所有的无向边进行定向,对于任何一条边,从度数大的点连向度数小的点,如果度数相同,从编号小的点连向编号大的点。

此时这张图是一个有向无环图。

  • 枚举每一个点u,然后将u的所有相邻的点都标记上“被u访问了”,
  • 然后再枚举u的相邻的点v,
  • 然后再枚举v的相邻的点w,
    如果w存在“被u访问了”的标记,那么(u,v,w)就是一个三元环了,且每个三元环只会被计算一次。

这样为什么是对的呢?
按照算法的流程,原来图中的一个三元环 \(((i,j,k)\) 在重定向之后一定变成了 i 向 j,k 连边,j,k 之间再连一条边的情况,不妨设为\(j \to k\) 。
我们枚举 i 时会标记 j,k ,再遍历 j找第三个点的时候一定会找到 k 。
并且对于这个环,遍历顺序只可能是 \(i\to j \to k\),也就是我们只能由 i 来找到这个环。每个点我们只会枚举一次,
所以图中的每一个三元环,我们都会遍历 且 仅遍历一次。

那么时间复杂度为什么 \(O(m\sqrt m)\) 呢?

考虑每条边 \((u,v)\) 对时间复杂度的贡献与 \(v\) 的出度同阶,总的时间复杂度应当是 $\sum_{i=1}^m d_v$,这里 \(d\) 是出度。

对于原图中度数不大于 \(\sqrt{m}\) 的点,新图中的度数也不可能更大,所以上界 \(\sqrt{m}\)。

对于原图中度数大于 \(\sqrt{m}\) 的点,由于我们只向度数大的点连边,而度数大于 \(\sqrt{m}\) 的点最多有 \(\sqrt{m}\)个,度数也不可能超过 \(\sqrt m\)。

综上,总的时间复杂度 \(O(m\sqrt{m})\)。

模板代码

时间复杂度 \(O(M \sqrt{M})\)


模板题

P1989 无向图三元环计数


C - Friend-Graph HDU - 6152

注意及时剪枝结束,不然会超时。
代码

#include<bits/stdc++.h>
using namespace std;
#define pii pair<int,int>  
#define int short int 
const int N=3010;
const int maxn=3010;
int vis[maxn];
typedef vector< vector<int> > Graph;
Graph G;
int n, u, v;
int m=0;
int getnum(){
  memset(vis,0,sizeof vis);

	for(int i = 1; i <= n; ++i) {
		for(int j : G[i])
			if(G[i].size() > G[j].size() || G[i].size() == G[j].size() && i > j) vis[j] = i;
		for(int j : G[i])
			if(G[i].size() > G[j].size() || G[i].size() == G[j].size() && i > j)
				for(int k : G[j])
					if(G[j].size() > G[k].size() || G[j].size() == G[k].size() && j > k)
						if(vis[k] == i)
							 return 1;
	}
   return 0;
}
void solve(){
    m=0;
   cin>>n;
   G.resize(n + 1);
   for(int i = 1; i <= n; ++i) {
           G[i].clear();
   }
//    cout<<G[1].size()<<endl;
//    cout<<G[1][2]<<endl;
   for(int i=1;i<=n-1;i++){
       for(int j=i+1;j<=n;j++){
          int t;cin>>t;
        if(t){
            int u=i,v=j;
              m++;
            G[u].push_back(v);
		    G[v].push_back(u);
         
        }
       }
   }
    // cout<<m<<endl;
    if(m>2e4) {
    cout<<"Bad Team!"<<endl;
    return ;
   }
   int ans1 = 0,ans2=0;
   ans1=getnum();
   m=n*(n-1)/2-m;
   if(m>2e4) {
    cout<<"Bad Team!"<<endl;
    return ;
   }
    for(int i = 1; i <= n; ++i) {
         memset(vis,0,sizeof vis);
		for(int j : G[i])
        {
            vis[j]=1;
        }
        G[i].clear();
        for(int j=1;j<=n;j++){
            if(vis[j]==0) G[i].push_back(j);
        }
    }
    
     ans2=getnum();

    if(ans1==0 &&  ans2==0) cout<<"Great Team!"<<endl;
    else  cout<<"Bad Team!"<<endl;

}

signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int t=1;
    cin>>t;

    while(t--) solve();
    return 0;
}

原文1:https://blog.51cto.com/u_15072778/3772333
原文2:https://www.luogu.com.cn/blog/i207M/san-yuan-huan-ji-shuo-xue-xi-bi-ji

标签:度数,int,复杂度,无向,sqrt,计数,查找,三元,size
From: https://www.cnblogs.com/kingwz/p/16664770.html

相关文章

  • 引用计数的存储
    在64位中,引用计数可以直接存储在优化过的isa指针中,也可能存储在SideTable类中。在isa里面,有一个extra_rc参数其中:rc就是retainCount引用计数的意思。则has_sidetable_r......
  • 统计数组中某个值出现的次数
    JavaScriptconstcountOccurrences=(arr,val)=>arr.reduce((a,v)=>(v===val?a+1:a),0)ExamplescountOccurrences([1,1,2,1,2,3],1)//3......
  • 二分查找对应三种区间的写法:
    //二分查找---[left,right]//数组已经是有序的了!publicstaticintbinarySerach1(int[]nums,inttarget){if(nums==null||nums.length......
  • 递归、二分查找
    #递归函数:有最大递归深度,默认接近1000,各版本略有差异count=0defF1(n):n+=1print(n)#123……996F1(n)F1(count)#修改递归深度importsys......
  • P5664[CSP-S2019] Emiya 家今天的饭 (dp + 计数)
     P5664[CSP-S2019]Emiya家今天的饭(dp+计数)题目传送门题目大意:给定一个大小为\(n*m\)的表格,其中\(a_{i,j}\)表示用第\(i\)种烹饪方式并且有第\(j\)......
  • idea的查找与替换
    查找当前文件内容:ctrl+F如上图片查找全局文件:ctrl+shift+F或doubleshift(按两下)或ctrl+shift+N替换当前文件内容:ctrl+R如上图片你想通过编辑器快速的将所有的......
  • source insight f3、F4循环查找
    摘自:https://blog.csdn.net/Decisiveness/article/details/50748596searchforward(F4)和searchbackward(F3)搜索时会循环,找不到设置的地方将这个特性取消,不要它循环,找一套so......
  • C# WinForm 按名称查找控件
    1///<summary>2///按名称查找控件3///</summary>4///<paramname="parentControl">查找控件的父容器控件</param>5///<paramname="findCtrlName">查......
  • .net通过iText操作pdf文件实现查找关键字签字盖章(新)
    因为上一篇文章确认有问题,后面复测发现bug,现在重新写了,是基于iText写的,复测多次,基本上没问题了。其他需要使用者自行扩展了直接贴代码吧。1usingiText.IO.Image;......
  • 通过 Infinity 和 -Infinity 查找数组中最大和最小值
    functionfindMaxNum(numbers){letmax=-Infinity;for(constnofnumbers){if(n>max){max=n;}}returnmax;}functionfindMi......