zoukankan      html  css  js  c++  java
  • 【并查集】【枚举倍数】UVALive

    题意:n个点,每个点有一个点权。两个点之间有边相连的充要条件是它们的点权不互素,问你这张图的连通块数。

    从小到大枚举每个素数,然后枚举每个素数的倍数,只要这个素数的某个倍数存在,就用并查集在这些倍数之间都连上边。然后输出最后的集合数量即可。

    注意,点权为1的点都会自成一个连通块。

    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int T,a[1000006],fa[1000006],f[1000006],p[1000006],ans,n,t,notPrime[1000006],prime[1000006],num;
    int get(int x){return fa[x]==x?x:fa[x]=get(fa[x]);}
    void un(int x,int y)
    {
        int Y=get(y);int X=get(x);
        if(X!=Y)
        {
            fa[X]=Y;
        }
    }
    char ch;
    int temp;
    int read()
    {
        while(ch=getchar(),ch<'0'||ch>'9');
        temp=ch-'0';
        while(ch=getchar(),ch<='9'&&ch>='0')
            temp=temp*10+ch-'0';
        return temp;
    }
    int main()
    {
     //   freopen("1.in","r",stdin);
      //  freopen("1.out","w",stdout);
        for(int i=2;i<=1000000;++i)
        {
            if(!notPrime[i])
            {
                prime[++num]=i;
            }
            for(int j=1;j<=num&&prime[j]*i<=1000000;++j)
            {
                notPrime[i*prime[j]]=1;
                if(i%prime[j]==0) break;
            }
        }
        scanf("%d",&T);
        int maxi=1000000;
        for(int tt=1;tt<=T;++tt)
        {
            n=read();
            for(int i=1;i<=maxi;++i)
            {
                fa[i]=i;
                f[i]=0;
                a[i]=0;
            }
            maxi=0;
            ans=0;
            for(int i=1;i<=n;++i)
            {
                t=read();
                if(t==1) ans++;
                maxi=max(maxi,t);
                a[t]=1;
            }
            for(int i=1;i<=num;++i)
            {
                int now=prime[i];
                int tail=0;
                for(int j=1;now*j<=maxi;++j)
                {
                    if(a[now*j])
                    p[++tail]=now*j;
                }
                for(int j=1;j<tail;++j)
                {
                    un(p[j],p[j+1]);
                }
            }
            for(int i=2;i<=maxi;++i)
            if(a[i])
            {
                if(!f[get(i)]) ans++;
                f[get(i)]=1;
            }
            printf("Case %d: %d
    ",tt,ans);
        }
    
    }
  • 相关阅读:
    vue与自定义元素的关系
    vue用组件构建应用
    vue处理用户输入
    vue条件与循环
    vue声明式渲染
    Java编程的逻辑 (86)
    Java编程的逻辑 (85)
    Java编程的逻辑 (84)
    Java编程的逻辑 (83)
    Java编程的逻辑 (82)
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7747464.html
Copyright © 2011-2022 走看看