基础数学 1002 LightOJ 1356

来源:互联网 发布:组策略映射网络驱动器 编辑:程序博客网 时间:2024/05/18 12:30

题意:
给你一个集合,找出最大的子集合,
该子集合里任意两个数x,y不能存在y/x=t,t是质数
思路:
因为是求最大独立集,所以容易想到二分图来建图
二分图左边放奇数个质因子的数,右边放偶数个质因子的数
然后如果y/x=t,t是质数,就把xy连边,一边二分图匹配就出来了
因为匈牙利的时间复杂度比较高,所以这里用Hopcroft-Carp
大概是O(sqrt(V)*E)

#include<stdio.h>#include<string.h>#include<iostream>#include<algorithm>#include<math.h>#include<queue>#include<stack>#include<string>#include<vector>#include<map>#include<set>using namespace std;#define lowbit(x) (x&(-x))typedef long long LL;const int maxn = 40005;const int inf=(1<<28)-1;#define N 500005vector<int>g[maxn];int um[N],vm[N],n;int dx[N],dy[N],dis;bool vis[N];void inserts(int u, int v){    g[u].push_back(v);}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<g[u].size();i++)        {            int v = g[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<g[u].size();i++)    {        int v = g[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(vm,-1,sizeof(vm));    memset(um,-1,sizeof(um));    for(int i=0;i<=n;i++)        g[i].clear();}#define maxp 500005bool notprime[maxp];int primes[maxp];void get_prime(){    notprime[1]=true;    for(int i=2;i<maxp;++i)    if(!notprime[i])    {        primes[++primes[0]]=i;        for(LL j=(LL)i*i;j<maxp;j+=i)        notprime[j]=true;    }}int A[maxn],B[maxp],Fac[105];int main(){    get_prime();    int Case=0,T;    scanf("%d",&T);    while(T--)    {        scanf("%d",&n);        init();        memset(B,-1,sizeof(B));        for(int i=1;i<=n;++i)            scanf("%d",&A[i]);        sort(A+1,A+n+1);        for(int i=1;i<=n;++i)            B[A[i]]=i;        for(int i=1;i<=n;++i)        {            int t=A[i],Cnt=0,Cnt2=0;            for(int j=1;primes[j]*primes[j]<=t;++j)            if(t%primes[j]==0)            {                t/=primes[j];                Fac[Cnt++]=primes[j];                Cnt2++;                while(t%primes[j]==0)                    t/=primes[j],Cnt2++;            }            if(t>1) Fac[Cnt++]=t,Cnt2++;            for(int j=0;j<Cnt;++j)            {                t=B[A[i]/Fac[j]];                if(t<=i&&t!=-1)                {                    if(Cnt2&1) inserts(i,t);                    else inserts(t,i);                }            }        }        printf("Case %d: %d\n",++Case,n-maxMatch());    }    return 0;}
0 0
原创粉丝点击