有 nn 种化学物质,编号 1∼n1∼n。
其中,有 mm 对物质之间会发生反应。
现在,要将这些化学物质逐个倒入同一个试管之中,具体倒入顺序不限。
我们需要计算一下试管的危险值。
已知,空试管的危险值为 11,每倒入一种化学物质,如果该物质能够与之前倒入试管中的一种或多种物质发生反应,则试管的危险值将乘以 22。
请你计算并输出,通过合理安排所有化学物质的倒入顺序,能够得到的试管的最大危险值。
输入格式
第一行包含两个整数 n,mn,m。
接下来 mm 行,每行包含两个整数 x,yx,y,表示化学物质 xx 和化学物质 yy 之间会发生反应。保证同一对化学物质在输入中最多出现一次。
输出格式
一个整数,表示最大危险值。
数据范围
前 4 个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤50,0≤m≤n(n−1)/2,1≤x<y≤n。
输入样例1:
1 0
输出样例1:
1
输入样例2:
2 1
1 2
输出样例2:
2
输入样例3:
3 2
1 2
2 3
输出样例3:
4
分析: 任何一个连通块或者环,都可以转化为上面树的形式,我们只需要从根节点开始遍历即可达到最大。所以题目就可以转化为求连通块的数量,连通块可以用并查集来求。
#include<iostream>
using namespace std;
const int N = 1010;
int p[N];
int find(int x)
{
if(p[x]!=x) p[x]=find(p[x]);
return p[x];
}
int main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
p[i]=i;
int cnt=n;
while(m--)
{
int x,y;
cin>>x>>y;
int pa = find(x);
int pb = find(y);
if(pa!=pb)
{
p[pa]=y;//把x节点的祖宗全部变为b节点的祖宗
cnt--;
}
}
cout<<(1ll<< n-cnt)<<endl;
return 0;
}