hihocoder1158 二分图的最大独立集

题目大意:中文题。

算法思路:首先找出每个数的质因数的个数,因为如果a和b是质数相关的话,那他们两个的质数的个数肯定是一奇,一偶,因此我们可以根据这个性质,将这些数分成两个部分,转化二分图的最大独立集求解,这道题我已开始用求解质因数的模板,结果发现这个模板对于相同的质因数只算一个(在这里wa了好多回=- =),后来只好打素数表求解。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
using namespace std;
#define MAXN 1005
#define MAXN2 5500000
int t,n,e,size1,size2;
int a[MAXN],match[MAXN],head[MAXN],nextt[MAXN];
int s1[MAXN],s2[MAXN];
bool maps[MAXN][MAXN];

bool visited2[MAXN];


typedef struct Edge
{
    int u,v,c;
};
Edge edges[MAXN];
/**
 * 线性筛法求素数表
 * 复杂度: O(n)
 */
int prime[MAXN2] = {0},num_prime = 0;
bool isNotPrime[MAXN2] = {true, true};
void GetPrime_Init()//初始化调用
{
    for(int i = 2 ; i <  MAXN2 ; i ++)
    {
        if(! isNotPrime[i])
            prime[num_prime ++]=i;
        for(int j = 0 ; j < num_prime && i * prime[j] <  MAXN2 ; j ++)
        {
            isNotPrime[i * prime[j]] = true;
            if( !(i % prime[j]))
                break;
        }
    }
}
bool isPrime(int x)
{
    for(int i=2;i*i<=x;i++)
    {
        if(x%i==0)
            return false;
    }
    return true;
}
void addNode(int u,int v,int c)
{
    edges[e].u=u;
    edges[e].v=v;
    edges[e].c=c;
    nextt[e]=head[u];
    head[u]=e++;
}
int dfs(int p)
{
     for(int i=head[p];i+1;i=nextt[i]){

        int v=edges[i].v;
        if(visited2[v])
            continue;
        visited2[v]=1;
        if(match[v]==-1||dfs(match[v])){
            match[v]=p;
            return 1;
        }
    }
    return 0;
}

void solve_div(int kk)
{
    int kk2=kk;
    int num=0;
    for(int i=0;prime[i]<=kk;i++)
    {
        while(kk%prime[i]==0)
        {
            num++;
            kk/=prime[i];
        }
    }
    if(num%2!=0)
    {
        s1[size1++]=kk2;
    }
    else
    {
        s2[size2++]=kk2;
    }
}

int main()
{
    GetPrime_Init();
    scanf("%d",&t);
    int cnt=0;
    while(t--)
    {
        size1=0,size2=0,e=0;
        memset(s1,0,sizeof(s1));
        memset(s2,0,sizeof(s2));
        memset(maps,false,sizeof(maps));
        memset(match,-1,sizeof(match));
        memset(head,-1,sizeof(head));
        memset(nextt,-1,sizeof(nextt));
        scanf("%d",&n);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&a[i]);
        }

        for(int i=1;i<=n;i++)
        {
            solve_div(a[i]);
        }

        for(int i=0;i<size1;i++)
        {
            for(int j=0;j<size2;j++)
            {
                if(s1[i]%s2[j]==0&&isPrime(s1[i]/s2[j]))
                {
                    addNode(i,j,1);
                }
                else if(s2[j]%s1[i]==0&&isPrime(s2[j]/s1[i]))
                {
                    addNode(i,j,1);
                }
            }
        }

        int sum=0;
       for(int i=0;i<size1;i++)
       {
           memset(visited2,false,sizeof(visited2));
           sum+=dfs(i);
       }

        printf("Case #%d: %d\n",++cnt,n-sum);

    }



    return 0;
}


 在这里再记录一下那个只记录一次的求解质因数的模板。

/*void Solve(int nn,int k)//利用容斥原理求解质因数
{
    v[k].clear();
    for(int i=2; i*i<=nn; i++)
    {
        if(nn%i==0)
        {
            v[k].push_back(i);
            while(nn%i==0) nn/=i;
        }
    }
    if(nn>1)
        v[k].push_back(nn);  //这个不可以缺少
}*/

猜你喜欢

转载自huyifan951124.iteye.com/blog/2327934
今日推荐