2015编程之美 初赛第一场C题 质数相关 二分图的最大匹配

质数相关

Time Limit: 1 Sec  Memory Limit: 256 MB

题目连接

http://hihocoder.com/contest/msbop2015round2a/problem/3

Description

两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数。一个集合S被称为质数相关,是指S中存在两个质数相关的数,否则称S为质数无关。如{2, 8, 17}质数无关,但{2, 8, 16}, {3, 6}质数相关。现在给定一个集合S,问S的所有质数无关子集中,最大的子集的大小。

Input

第一行为一个数T,为数据组数。之后每组数据包含两行。

第一行为N,为集合S的大小。第二行为N个整数,表示集合内的数。

Output

对于每组数据输出一行,形如"Case #X: Y"。X为数据编号,从1开始,Y为最大的子集的大小。

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

 

HINT

 

1 ≤ T ≤ 20

集合S内的数两两不同且范围在1到500000之间。

小数据

1 ≤ N ≤ 15

大数据

1 ≤ N ≤ 1000

题意

 

题解:

首先我们把题目转化一下,我们由所给的质数关系,我们可以得到 每一个数可以和哪些数在一起的图

然后我们就可以转化成二分图的最大匹配了!

唔 另一道题可见:http://www.cnblogs.com/qscqesze/p/4414246.html

代码:

 

//qscqesze
#include <cstdio>
#include <cmath>
#include <cstring>
#include <ctime>
#include <iostream>
#include <algorithm>
#include <set>
#include <vector>
#include <sstream>
#include <queue>
#include <typeinfo>
#include <fstream>
#include <map>
#include <stack>
typedef long long ll;
using namespace std;
//freopen("D.in","r",stdin);
//freopen("D.out","w",stdout);
#define sspeed ios_base::sync_with_stdio(0);cin.tie(0)
#define maxn 200001
#define mod 10007
#define eps 1e-9
int Num;
char CH[20];
//const int inf=0x7fffffff;   //нчоч╢С
const int inf=0x3f3f3f3f;
/*

inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
*/
//**************************************************************************************
inline ll read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline void P(int x)
{
    Num=0;if(!x){putchar('0');puts("");return;}
    while(x>0)CH[++Num]=x%10,x/=10;
    while(Num)putchar(CH[Num--]+48);
    puts("");
}
const int MAXN = 500001;
bool flag[MAXN];
int primes[MAXN], pi;
void GetPrime_1()
{
    int i, j;
    pi = 0;
    memset(flag, false, sizeof(flag));
    for (i = 2; i < MAXN; i++)
        if (!flag[i])
        {
            primes[i] = 1;//素数标识为1
            for (j = i; j < MAXN; j += i)
                flag[j] = true;
        }
}

vector<int> q[maxn];
int vis[maxn];
int match[maxn];
int a[maxn];
bool cmp(int b,int c)
{
    return b>c;
}
int dfs(int x)
{
    for(int i=0;i<q[x].size();i++)
    {
        if(vis[q[x][i]]==0)
        {
            vis[q[x][i]]=1;
            if(match[q[x][i]]==-1||dfs(match[q[x][i]]))
            {
                match[q[x][i]]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    GetPrime_1();
    primes[1]=0;
    int t=read();
    for(int cas=1;cas<=t;cas++)
    {
        memset(match,-1,sizeof(match));
        int n=read();
        for(int i=0;i<n;i++)
            q[i].clear();
        for(int i=0;i<n;i++)
            a[i]=read();
        sort(a,a+n,cmp);
        for(int i=0;i<n;i++)
        {
            for(int j=0;j<n;j++)
            {
                if(i==j)
                    continue;
                int b=a[j];
                int c=a[i];
                if(b<c)
                    swap(b,c);
                if(b%c==0&&primes[b/c])
                {
                    q[j].push_back(i);
                }
            }
        }
        int ans=0;
        for(int i=0;i<n;i++)
        {
            memset(vis,0,sizeof(vis));
            if(dfs(i))
                ans++;
        }
        printf("Case #%d: %d\n",cas,n-ans/2);
    }

}

 

你可能感兴趣的:(编程之美)