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);  //这个不可以缺少
}*/

 

源码地址: https://pan.quark.cn/s/d1f41682e390 miyoubiAuto 米游社每日米游币自动化Python脚本(务必使用Python3) 8更新:更换cookie的获取地址 注意:禁止在B站、贴吧、或各大论坛大肆传播! 作者已退游,项目不维护了。 如果有能力的可以pr修复。 小引一波 推荐关注几个非常可爱有趣的女孩! 欢迎B站搜索: @嘉然今天吃什么 @向晚大魔王 @乃琳Queen @贝拉kira 第三方库 食用方法 下载源码 在Global.py中设置米游社Cookie 运行myb.py 本地第一次运行时会自动生产一个文件储存cookie,请勿删除 当前仅支持单个账号! 获取Cookie方法 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 按刷新页面,按下图复制 Cookie: How to get mys cookie 当触发时,可尝试按关闭,然后再次刷新页面,最后复制 Cookie。 也可以使用另一种方法: 复制代码 浏览器无痕模式打开 http://user.mihoyo.com/ ,登录账号 按,打开,找到并点击 控制台粘贴代码并运行,获得类似的输出信息 部分即为所需复制的 Cookie,点击确定复制 部署方法--腾讯云函数版(推荐! ) 下载项目源码和压缩包 进入项目文件夹打开命令行执行以下命令 xxxxxxx为通过上面方式或取得米游社cookie 一定要用双引号包裹!! 例如: png 复制返回内容(包括括号) 例如: QQ截图20210505031552.png 登录腾讯云函数官网 选择函数服务-新建-自定义创建 函数名称随意-地区随意-运行环境Python3....
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值