UVALive 7638

题目大意:两个结点之间的gcd>1,那么这两个结点就可以建边,问最终有几个联通块。

题目思路:想到了并查集,但是单纯使用就T掉了O(n^2)。看了网上别的大神的博客,大体思路是这样的:把每个数进行质因数分解,然后把这个数和他的质因数建边。那么只要有相同质因数的两个数都会在同一个联通块里,因为x1<=1e6,那么遍历1~1e6的所有数字,该有边的肯定会在一个联通块里面O(n)。(比赛时候没想到,下回注意,放在这里提醒自己)。

代码如下:


#include 
#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const int maxm=1000005;
int n,a[maxm];
int par[maxm],rak[maxm];
bool vis[maxm];
int ans;
vector g[maxm];
void inite()
{
    for(int i=1;i<=maxm;i++)
    {
        par[i]=i;
        rak[i]=0;
    }
}
int find(int x)
{
    if(par[x]==x) return x;
    else {
            return par[x]=find(par[x]); 
    }
}
void unite(int x,int y)
{
    x=find(x);
    y=find(y);
    if(x==y) return;
    if(rak[x]



你可能感兴趣的:(uva)