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

来源:互联网 发布:以下哪种立体匹配算法 编辑:程序博客网 时间:2024/04/30 10:23

 Prime Independence
Time Limit:3000MS     Memory Limit:32768KB     64bit IO Format:%lld & %llu
Submit Status Practice LightOJ 1356

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 40010int 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\n",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 40010int 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\n",++kk,n-maxMatch());    }    return 0;}




0 0