CF445B DZY Loves Chemistry 题解

题目传送门

Solution:

并查集裸题。

\(1\)\(m\) 枚举,判断编号为 \(i\) 两种物质是否反应过(是否在一个并查集里),是则跳过,反之将这两个点所在的集合合并,并更新答案。

注意:

  • 初始化并查集

  • \(\text{ans}\) 初值要设为 \(1\),以后的 \(\times 2\) 操作才会生效。

  • 因为 \(1 \le n \le 50\),所以答案最大为 \(2^{49}\)需要开 \(\text{long long}\)

Code:

#include<bits/stdc++.h>   //万能头文件  
#define int long long
using namespace std; 

int f[1<<20];

void init(int x) //初始化函数
{
	f[0]=0;
	for(int i=1;i<=x;i++)
	{
		f[i]=i;//一开始,每个节点的爸爸都是它本身
	}
}

int find(int x) //找爸爸函数
{
	if(f[x]==x) return x;
	return f[x]=find(f[x]);//路径压缩
}

void merge(int x,int y) //加点函数
{
	int fx=find(x),fy=find(y);
	if(fx==fy) return;
	f[fx]=fy;
}

int n,m,ans=1;
struct R { int u,v,w; } a[1<<20];

signed main()
{
	cin>>n>>m;
	
	init(n);//初始化,有 n 个点的并查集
	
	for(int i=1;i<=m;i++) cin>>a[i].u>>a[i].v;
		
	for(int i=1;i<=m;i++)
	{
		int fx=find(a[i].u);
		int fy=find(a[i].v);//找这两个点的爸爸
		if(fx!=fy)
		{
			f[fx]=fy;// 合并集合
			ans<<=1; //ans*=2,计算答案
		}
	}
	
	cout<<ans;
	
	return 0;
}
posted @ 2025-02-08 16:39  Wy_x  阅读(9)  评论(0)    收藏  举报