当前位置: 首页 > news >正文

[leetcode]2685. 统计完全连通分量的数量

题目链接

题意

给定无向图,求完全连通分量
连通分量就是一个连通块的意思
完全连通分量:就是一个连通块中 ,所有点之间都两两有边相连

思路

一个完全联通分量有n个点 那么应该有 C n 2 C_n^2 Cn2条边
并查集维护连通块
检查每个联通分量是否有 C n 2 C_n^2 Cn2条边
如果有就ans++

Code

#define pii pair<int,int>
#define ar2 array<int,2>
#define ar3 array<int,3>
#define ar4 array<int,4>
#define endl '\n'
void cmax(int &a,int b){a=max(a,b);};
void cmin(int &a,int b){a=min(a,b);};
const int N=1e5+10,MOD=1e9+7,INF=0x3f3f3f3f;const long long LINF=LLONG_MAX;const double eps=1e-6;
int a[N];

class UnionFind{
private:
    vector<int>p,s,ecnt;//ecnt[i]表示以find(i)为根的连通块的边数
    unordered_set<int>roots;
public:
    UnionFind(int n): p(n+1),s(n+1,1),ecnt(n+1,0){//多开一个空间 同时适用于0-based&1-based
        iota(p.begin(),p.end(),0);
        for(int i=0;i<n;i++){//如果1-based就改成i->[1,n]
        	roots.insert(i);
        }
    }

    int find(int x){
        if(p[x]!=x) p[x]=find(p[x]);
        return p[x];
    }

    void merge(int u,int v){
        int uu=find(u),vv=find(v);
        if(uu!=vv){
            if(s[uu]>s[vv]){
                p[vv]=uu;
                s[uu]+=s[vv];
                ecnt[uu]+=ecnt[vv]+1;
                roots.erase(vv);
            }else {
                p[uu]=vv;
                s[vv]+=s[uu];
                ecnt[vv]+=ecnt[uu]+1;
                roots.erase(uu);
            }
        }else{
			ecnt[uu]++;//已经联通了也要加边数
		}
    }
    
	bool is_connected(int u,int v){
        return find(u)==find(v);
    }
    
    int size(int x){
        return s[find(x)];
    }	

	int get_ecnt(int x){
		return ecnt[find(x)];
	}    

    vector<int>get_roots(){
		return vector<int>(roots.begin(),roots.end());
	}
	
	int get_cnt(){
		return roots.size();
	}
};

using ll = long long;

ll c[60][60];
void init(){
    for(int i=0;i<60;i++){
        c[i][0]=c[i][i]=1;
        for(int j=1;j<i;j++){
            c[i][j]=c[i-1][j-1]+c[i-1][j];
        }
    }
}

class Solution {
public:
    int countCompleteComponents(int n, vector<vector<int>>& edges) {
        UnionFind uf(n);
        for(auto e:edges){
            int u=e[0],v=e[1];
            uf.merge(u,v);
        }
        init();
        auto v=uf.get_roots();
        int ans=0;

        for(int i:v){
            if(c[uf.size(i)][2]==uf.get_ecnt(i)) ans++;
        }
        return ans;

    }
};

不能直接用阶乘算,分分钟溢出,我用了递推约分

相关文章:

  • C++ 结构体、结构体指针与结构体指针数组详解
  • RabbitMQ 的三种集群模式
  • ETL数据集成:企业数字化转型的核心驱动力与实施策略
  • C++ Primer Plus 编程练习题 第五章 循环和关系表达式
  • 22-ArkTs 常见错误
  • DataPlatter:利用最少成本数据提升机器人操控的泛化能力
  • K8S学习之基础六十四:helm常用命令
  • 戴尔电脑安装Ubuntu双系统
  • 设计模式中的“万能转换器”——适配器模式
  • 【AI News | 20250331】每日AI进展
  • 鸿蒙编译构建-多目标产物
  • Scala循环守卫
  • vi编辑器常见命令
  • stm32第十一天外部中断按键控制灯
  • 自定义类型:结构体
  • 【Java】——数组深度解析(从内存原理到高效应用实践)
  • CentOS 7上手动强制升级docker-compose(不使用yum)
  • 苍穹外卖项目结构
  • Loadrunner报错Virtual User Generator 初始化用户生成器失败 初始化失败
  • AI产品的架构(分四层)
  • 云服务器怎么样做网站/优化大师官网登录入口
  • 什么能建我的网站呢/seo优化案例
  • 廊坊网站建设/合肥seo按天收费
  • 一般网站如何做防采集的/广州网站运营专注乐云seo
  • 网站建设的用户名和密码代码/汕头seo外包公司
  • 临沂网站建设小程序/百度相册登录入口