集合个数(并查集)

题目描述
Caima 给你了所有 [a,b] 范围内的整数。一开始每个整数都属于各自的集合。每次你需要选择两个属于不同集合的整数,如果这两个整数拥有大于等于 p 的公共质因数,那么把它们所在的集合合并。

重复如上操作,直到没有可以合并的集合为止。

现在 Caima 想知道,最后有多少个集合。

输入格式
一行,共三个整数 a,b,p,用空格隔开。

输出格式
一个数,表示最终集合的个数。

输入输出样例
输入 
10 20 3
输出
7

说明/提示
样例 1 解释
对于样例给定的数据,最后有 {10,20,12,15,18},{13},{14},{16},{17},{19},{11} 共 7 个集合,所以输出应该为 7。

数据规模与约定
对于 80%80% 的数据,10^31≤a≤b≤10 ^3 。
对于 100%100 的数据,1≤a≤b≤10^5,2≤p≤b。

用并查集算法
下面的代码数据大就超时了…

#include
using namespace std;

const int N=110000;

int f[N];
int a,b,p;
set<int>s;

void init()
{
	for(int i=0;i<=N;i++)
		f[i]=i;
}

int prime(int x)
{
	if(x<=1)
		return 0;
	for(int i=2;i<=sqrt(x);i++)
	{
		if(x%i!=0)
			return 0;
	}
	return 1;
}

int judge(int x,int y)
{
	int minn=min(x,y);
	int maxn=max(x,y);
	if(minn<p||maxn<p)
		return 0;
	for(int i=p;i<=minn;i++)
	{
		if(prime(i))
		{
			if(minn%i==0&&maxn%i==0)
				return 1;	
		}	
	}	
	return 0;
}

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


void join(int x,int y)
{
  	int tx=find(x);
	int ty=find(y);
	if(tx!=ty)
		f[tx]=ty;
}

int main()
{
	init();
	cin>>a>>b>>p;
	for(int i=a;i<=b-1;i++)
	{
		for(int j=i+1;j<=b;j++)
		{
			if(judge(i,j))
			{
				join(i,j);
			}
		}
	}
	for(int i=a;i<=b;i++)
	{
		int x=find(i);
		s.insert(x);
	}
	
//	for(set::iterator it=s.begin();it!=s.end();it++)
//	{
//		cout<<*it<<" ";
//	}
 	cout<<s.size(); 
	
	return 0;	
} 

你可能感兴趣的:(算法,数据结构,并查集)