lightoj 1356 Prime Independence(最大独立集+HK算法)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37943488/article/details/82318711

1356 - Prime Independence

    PDF (English) Statistics Forum
Time Limit: 3 second(s) Memory Limit: 32 MB

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 multiple of 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

Output for Sample Input

3

5

2 4 8 16 32

5

2 3 4 6 9

3

1 2 3

Case 1: 3

Case 2: 3

Case 3: 2

Note

1.      An integer is said to be a prime if it's divisible by exactly two distinct integers. First few prime numbers are 2, 3, 5, 7, 11, 13, ...

2.      Dataset is huge, use faster I/O methods.

题目大意:给你一个集合,问最大的子集满足集合内任意两个数都不能通过乘素数得到。

最大独立集=点数-匹配数

这道题卡匈牙利,只能用HK写,算是存个模板吧

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define debug cout<<"test"<<endl
const int maxn=4e4+7;
const int maxm=1e6+107;
const int inf=0x3f3f3f3f;
struct Node
{
	int to;
	int next;
}edge[maxm];
int cnt;
int odd,even;
int id[500010];
int num[maxn];
int head[maxn];
bool prime[500010];
int prime_cnt[500010];
bool vis[500010];
int match[500010];
int vis_index[500010];
void init()
{
	memset(head,-1,sizeof(head));
	memset(vis,false,sizeof(vis));
	memset(vis_index,0,sizeof(vis_index));
	cnt=0;
	odd=even=0;
	return;
}
void add(int u,int v)
{
	edge[cnt].to=v;
	edge[cnt].next=head[u];
	head[u]=cnt++;
	return;
}
void init_prime()
{
	memset(prime,false,sizeof(prime));
	prime[1]=true;
	for(int i=2;i<=500000;i++)
	{
		if(prime[i]==false)
		{
			for(int j=i+i;j<=500000;j+=i)
			{
				prime[j]=true;
			}
		}
	}
	return;
}
void getPrimeSum()
{
	for(int i=1;i<=500000;i++)
	{
		int num_cnt=0;
		int x=i;
		for(int j=2;j*j<=i;j++)
		{
			if(x%j==0)
			{
				while(x%j==0)
				{
					num_cnt++;
					x/=j;
				}
			}
		}
		if(x>1)
		{
			num_cnt++;
		}
		prime_cnt[i]=num_cnt;
	}
	return;
}
int uN;
int Mx[maxn],My[maxn];
int dx[maxn],dy[maxn];
int dis;
bool used[maxn];
bool dfs(int node)
{
    for(int i=head[node];~i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(!used[v]&&dy[v]==dx[node]+1)
        {
            used[v]=true;
            if(My[v]!=-1&&dy[v]==dis)
            {
                continue;
            }
            if(My[v]==-1||dfs(My[v]))
            {
                My[v]=node;
                Mx[node]=v;
                return true;
            }
        }
    }
    return false;
}
bool searchP()
{
    queue<int> que;
    dis=inf;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=1;i<=uN;i++)
    {
        if(Mx[i]==-1)
        {
            que.push(i);
            dx[i]=0;
        }
    }
    while(!que.empty())
    {
        int node=que.front();
        que.pop();
        if(dx[node]>dis) break;
        for(int i=head[node];~i;i=edge[i].next)
        {
            int v=edge[i].to;
            if(dy[v]==-1)
            {
                dy[v]=dx[node]+1;
                if(My[v]==-1)
                {
                    dis=dy[v];
                }
                else
                {
                    dx[My[v]]=dy[v]+1;
                    que.push(My[v]);
                }
            }
        }
    }
    return dis!=inf;
}
int HK()
{
    int res=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(searchP())
    {
        memset(used,false,sizeof(used));
        for(int i=1;i<=uN;i++)
        {
            if(Mx[i]==-1&&dfs(i))
            {
                res++;
            }
        }
    }
    return res;
}
int top;
int p[110];
void ldj(int x)
{
	top=0;
	for(int i=2;i*i<=x;i++)
	{
		if(x%i==0)
		{
			p[top++]=i;
			while(x%i==0)
			{
				x/=i;
			}
		}
	}
	if(x>1)
	{
		p[top++]=x;
	}
	return;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	init_prime();
	getPrimeSum();
	int test;
	scanf("%d",&test);
	for(int cas=1;cas<=test;cas++)
	{
		init();
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)
		{
			scanf("%d",&num[i]);
			int x=prime_cnt[num[i]];
			vis_index[num[i]]=i;
			if(x&1)
			{
				id[i]=++odd;
			}
			else
			{
				id[i]=++even;
			}
		}
		for(int i=1;i<=n;i++)
		{
			ldj(num[i]);
			for(int j=0;j<top;j++)
			{
				int x=num[i]/p[j];
				int ind=vis_index[x];
				if(ind)
				{
					if(prime_cnt[num[i]]&1&&prime_cnt[num[ind]]%2==0)
					{
						add(id[i],id[ind]);
					}
					else if(prime_cnt[num[i]]%2==0&&prime_cnt[num[ind]]&1)
					{
						add(id[ind],id[i]);
					}
				}
			}
		}
		uN=odd;
		printf("Case %d: %d\n",cas,n-HK());
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_37943488/article/details/82318711