• Prime Independence(质因子分解+二分图最大独立集)


     Prime Independence
    Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu

    Description

    A set of integers is called prime independent if none of its member is a prime multiple of another member. An integer a is said to be a prime multipleof b if,

    a = b x k (where k is a prime [1])

    So, 6 is a prime multiple of 2, but 8 is not. And for example, {2, 8, 17} is prime independent but {2, 8, 16} or {3, 6} are not.

    Now, given a set of distinct positive integers, calculate the largest prime independent subset.

    Input

    Input starts with an integer T (≤ 20), denoting the number of test cases.

    Each case starts with an integer N (1 ≤ N ≤ 40000) denoting the size of the set. Next line contains N integers separated by a single space. Each of these N integers are distinct and between 1 and 500000 inclusive.

    Output

    For each case, print the case number and the size of the largest prime independent subset.

    Sample Input

    3

    5

    2 4 8 16 32

    5

    2 3 4 6 9

    3

    1 2 3

    Sample Output

    Case 1: 3

    Case 2: 3

    Case 3: 2


    感觉超棒的一道题,值得一做。。。挺巧妙的。。。


    找出一个集合中的最大独立集,任意两数字之间不能是素数倍数的关系。

    思路:

    最大独立集,必然是二分图。

    最大数字50w,考虑对每个数质因子分解,然后枚举所有除去一个质因子后的数是否存在,存在则建边,考虑到能这样建边的数一定是质因子个数奇偶不同,所以相当于按奇偶区分建立了二分图,然后求二分图最大匹配,得到最大独立集就行了。



    #pragma comment(linker, "/STACK:102400000,102400000"
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<string>
    #include<map>
    #include<set>
    #include<ctime>
    #define eps 1e-6
    #define MAX 100005
    #define INF 0x3f3f3f3f
    #define LL long long
    #define pii pair<int,int>
    #define rd(x) scanf("%d",&x)
    #define rd2(x,y) scanf("%d%d",&x,&y)
    ///map<int,int>mmap;
    ///map<int,int >::iterator it;
    using namespace std;
    
    #define N 500010
    #define M 40010
    
    int a[M],b[N],num[M],factor[1000];
    vector<int>mmap[M];
    int n;
    bool vis[M];
    int linker[M];
    
    
    bool dfs(int u)
    {
        for(int i=0;i<mmap[u].size();i++)
        {
            if(!vis[mmap[u][i]])
            {
                vis[mmap[u][i]]=true;
                if(linker[ mmap[u][i] ]==-1||dfs(linker[ mmap[u][i] ]))
                {
                    linker[mmap[u][i]]=u;
                    return true;
                }
            }
        }
        return false;
    }
    
    int hungary()
    {
        int u;
        int res=0;
        for(u=1;u<=n;u++)
        {
            memset(vis,false,sizeof(vis));
            if(dfs(u))
                res++;
        }
        return res;
    }
    
    void init()
    {
        memset(num,0,sizeof(num));
        memset(b,0,sizeof(b));
        memset(linker,-1,sizeof(linker));
        for(int i=1;i<=n;i++)
            mmap[i].clear();
    }
    int main()
    {
        int T,Case,t;
    
        scanf("%d",&T);
        Case=1;
        while(T--)
        {
            scanf("%d",&n);
            init();
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
                b[ a[i] ]=i;  ///对节点哈希
    
            for(int i=1;i<=n;i++)
            {
                t = a[i];
                int cnt=0,sum=0; ///分解质因子 cnt质因子个数 sum为多少个质因子的积
                for(int j=2;t>1&&j<=sqrt(t) ;j++)
                    if(t%j==0)
                    {
                         factor[cnt++] = j;
                         while(t%j==0)
                            t/=j,sum++;
                    }
                if(t>1) //t有可能是质数
                    factor[cnt++]=t,sum++;
                num[i] = sum;
    
                for(int j=0;j<cnt;j++)
                {
                    t = b[  a[i] / factor[j]  ];
                    if(t==0) ///都是奇数或者偶数
                        continue;
                    if((sum&1)) ///是奇数 作为x部
                        mmap[i].push_back(t);
                    else   ///是偶数
                       mmap[t].push_back(i);
                }
            }
            printf("Case %d: %d
    ",Case++,n-hungary());
        }
        return 0;
    }
    


    Hopcroft-Karp,数组有点乱。。。

    #pragma comment(linker, "/STACK:102400000,102400000"
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<vector>
    #include<map>
    #include<queue>
    #include<stack>
    #include<string>
    #include<map>
    #include<set>
    #include<ctime>
    #define eps 1e-6
    #define MAX 100005
    #define INF 0x3f3f3f3f
    #define LL long long
    #define pii pair<int,int>
    #define rd(x) scanf("%d",&x)
    #define rd2(x,y) scanf("%d%d",&x,&y)
    ///map<int,int>mmap;
    ///map<int,int >::iterator it;
    using namespace std;
    
    #define N 500010
    #define M 40010
    
    int a[N],b[N],num[N],factor[1000];
    
    vector<int>mmap[M];
    int um[N],vm[N],n;
    int dx[M],dy[M],dis;
    bool vis[M];
    
    bool searchP()
    {
        queue<int>q;
        dis=INF;
        memset(dx,-1,sizeof(dx));
        memset(dy,-1,sizeof(dy));
        for(int i=1;i<=n;i++)
            if(um[i]==-1)
            {
                q.push(i);
                dx[i]=0;
            }
        while(!q.empty())
        {
            int u=q.front();q.pop();
            if(dx[u]>dis)  break;
            for(int i=0;i<mmap[u].size();i++)
            {
                int v = mmap[u][i];
                if(dy[v]==-1)
                {
                    dy[v]=dx[u]+1;
                    if(vm[v]==-1)  dis=dy[v];
                    else
                    {
                        dx[vm[v]]=dy[v]+1;
                        q.push(vm[v]);
                    }
                }
            }
        }
        return dis!=INF;
    }
    bool dfs(int u)
    {
        for(int i=0;i<mmap[u].size();i++)
        {
            int v = mmap[u][i];
            if(!vis[v]&&dy[v]==dx[u]+1)
            {
                vis[v]=1;
                if(vm[v]!=-1&&dy[v]==dis) continue;
                if(vm[v]==-1||dfs(vm[v]))
                {
                    vm[v]=u;um[u]=v;
                    return 1;
                }
            }
        }
        return 0;
    }
    int maxMatch()
    {
        int res=0;
        memset(um,-1,sizeof(um));
        memset(vm,-1,sizeof(vm));
        while(searchP())
        {
            memset(vis,0,sizeof(vis));
            for(int i=1;i<=n;i++)
              if(um[i]==-1&&dfs(i))
                res++;
        }
        return res;
    }
    
    void init()
    {
        memset(b,-1,sizeof(b));
        memset(num,0,sizeof(num));
        memset(vm,-1,sizeof(vm));
        memset(um,-1,sizeof(um));
        for(int i=0;i<=n;i++)
            mmap[i].clear();
    }
    int main()
    {
        int k,kk,t,x,y,z;
    
        scanf("%d",&k);
        kk=0;
        while(k--)
        {
            scanf("%d",&n);
            init();
            for(int i=1;i<=n;i++)
                scanf("%d",&a[i]);
            for(int i=1;i<=n;i++)
                b[ a[i] ]=i;
    
            for(int i=1;i<=n;i++)
            {
                t = a[i];
                int cnt=0,sum=0; ///分解质因子 cnt质因子个数 sum为多少个质因子的积
                for(int j=2;t>1&&j<=sqrt(t) ;j++)
                    if(t%j==0)
                    {
                         factor[cnt++] = j;
                         while(t%j==0)
                            t/=j,sum++;
                    }
                if(t>1) //t有可能是质数
                    factor[cnt++]=t,sum++;
                num[i] = sum;
    
                for(int j=0;j<cnt;j++)
                {
                    t = b[  a[i] / factor[j]  ];
                    if(  t==0 ) ///都是奇数或者偶数
                        continue;
                    if((sum&1)) ///是奇数 作为x部
                        mmap[i].push_back(t);
                    else   ///是偶数
                       mmap[t].push_back(i);
                }
            }
            printf("Case %d: %d
    ",++kk,n-maxMatch());
        }
        return 0;
    }
    




  • 相关阅读:
    SQL中存储过程与自定义函数的区别
    内置函数
    正则表达式
    HTML发展史
    触发器
    事务
    视图
    索引的使用
    存储过程和自定义函数的区别
    游标用法
  • 原文地址:https://www.cnblogs.com/zswbky/p/6717950.html
Copyright © 2020-2023  润新知