Lightoj-1356 Prime Independence(质因子分解&&二分图最大独立集)

来源:互联网 发布:游戏优化怎么做 编辑:程序博客网 时间:2024/05/18 01:57

题目:

http://lightoj.com/volume_showproblem.php?problem=1356

题意:

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

思路:

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

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

有一点这个题数据比较大,直接匈牙利炸了,要Hopcroft-Karp优化才能过。

代码:

//kopyh#include <bits/stdc++.h>#define INF 0x3f3f3f3f#define MOD 1000000007#define N 51234using namespace std;int n,m,sum,res,flag;bool mark[10*N];int pri[N],cnt;void SP(){    cnt=0;    memset(mark,true,sizeof(mark));    mark[0]=mark[1]=false;    for(int i=2;i<10*N;i++)    {        if(mark[i])            pri[cnt++]=i;        for (int j=0;(j<cnt)&&(i*pri[j]<10*N);j++)        {            mark[i*pri[j]]=false;            if (i%pri[j]==0)                break;        }    }}int pos[10*N],num[N];int f[N];int vm[N],um[N];bool vis[N];vector<int>g[N];int dx[N],dy[N],dis;void init(){    n=m=0;    memset(pos,0,sizeof(pos));    memset(f,-1,sizeof(f));    memset(vm,-1,sizeof(vm));    memset(um,-1,sizeof(um));    for(int i=0;i<=sum;i++)        g[i].clear();}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<=sum;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;    while(searchP())    {        memset(vis,0,sizeof(vis));        for(int i=1;i<=sum;i++)          if(um[i]==-1&&dfs(i))  res++;    }    return res;}int tmp[N],now,all;void solve(int t,int tot){    now = all = 0;    int tt=t;    for(int i=0;i<cnt&&pri[i]*pri[i]<=tt;i++)    {        if(tt%pri[i]==0)            tmp[now++] = pri[i];        while(tt%pri[i]==0)            tt/=pri[i],all++;    }    if(tt>1)tmp[now++] = tt, all++;    f[tot]=1&all;    if(f[tot])n++;    else m++;    for(int i=0;i<now;i++)    {        int x=t/tmp[i];        if(pos[x])        {            if(!f[tot])inserts(tot,pos[x]);            else inserts(pos[x],tot);        }    }}int main(){    int i,j,k,cas,T,t,x,y,z;    #ifndef ONLINE_JUDGE        freopen("test.txt","r",stdin);    #endif    SP();    scanf("%d",&T);    cas=0;    while(T--)    {        scanf("%d",&sum);        init();        for(i=1;i<=sum;i++)            scanf("%d",&num[i]);        for(i=1;i<=sum;i++)            pos[num[i]] = i;        for(i=1;i<=sum;i++)            solve(num[i],i);        printf("Case %d: %d\n",++cas,sum-maxMatch());    }    return 0;}







0 0
原创粉丝点击