题目链接:https://vjudge.net/problem/LightOJ-1356

题目大意:

  T个 test case,每个 test case 给出一个 N 个数的集合。请找出一个最大的子集,使得子集中的任何一个数除以子集中的任意的另一个数所得到的数不是质数。

解题思路:

  先用素数筛找出 1 到 500000 的所有质数。

  在输入一个集合的时候,我们顺便记录下输入的这个数在输入数组中的位置,找出它的所有质因数,记录下质因数的总个数,用一个vector记录下所有 “不同的” 质因数。

  遍历输入数组中的每一个数,对于每个数,遍历其所有 “不同的” 质因数,如果找到这样的一个质因数:该数除以这个质因数能得到输入数组中的另一个数,那么将这两个数连边。

  将由上述的连边操作得到的图中的点分成两类:质因数总个数为奇数的点和质因数总个数为偶数的点(这个划分有点隐晦,我多说两句:其实,对于连边的两个数,二者各自的所有质因数其实就只有一个质数的差别,其中一个数的所有质因数中有这个质数,但另一个数没有,其他的质因数都相同;所以,他们质因数的总个数相差 1,故其中一个为奇数,一个为偶数),这样一来,这个图就变成一个二分图了。而答案其实就是求这个二分图的最大独立集。

  另:用匈牙利算法者,T!用 Hopcroft-Carp者方有可能AC。

AC代码:

 #include <cstdio>
#include <algorithm>
#include <cstring>
#include <vector>
#include <queue> using namespace std;
const int inf=0x3f3f3f3f; bool prime[];
int have[],num[];
int prims[]; vector<int> G[];
int uN;
int l[];
int Mx[],My[];
int dx[],dy[];
int dis;
bool used[];
bool SearchP(){
queue<int>Q;
dis=inf;
memset(dx,-,sizeof(dx));
memset(dy,-,sizeof(dy));
for(int i=;i<uN;i++){
if(Mx[l[i]]==-){
Q.push(l[i]);
dx[l[i]]=;
}
}
while(!Q.empty()){
int u=Q.front();
Q.pop();
if(dx[u]>dis) break;
int sz=G[u].size();
for(int i=;i<sz;i++){
int v=G[u][i];
if(dy[v]==-){
dy[v]=dx[u]+;
if(My[v]==-) dis=dy[v];
else{
dx[My[v]]=dy[v]+;
Q.push(My[v]);
}
}
}
}
return dis!=inf;
}
bool DFS(int u){
int sz=G[u].size();
for(int i=;i<sz;i++){
int v=G[u][i];
if(!used[v]&&dy[v]==dx[u]+){
used[v]=true;
if(My[v]!=-&&dy[v]==dis) continue;
if(My[v]==-||DFS(My[v])){
My[v]=u;
Mx[u]=v;
return true;
}
}
}
return false;
}
int MaxMatch(){
int res=;
memset(Mx,-,sizeof(Mx));
memset(My,-,sizeof(My));
while(SearchP()){
memset(used,false,sizeof(used));
for(int i=;i<uN;i++){
if(Mx[l[i]]==-&&DFS(l[i])) res++;
}
}
return res;
}
void init(){
memset(prime,true,sizeof(prime));
prime[]=prime[]=false;
int cnt=;
for(int i=;i<=;i++){
if(prime[i]){
prims[cnt++]=i;
for(int j=*i;j<=;j+=i)
prime[j]=false;
}
}
}
int zhis[];
vector<int> zhiyinshu[];
int main(){
init();
int T,N;
scanf("%d",&T);
for(int t=;t<=T;t++){
scanf("%d",&N);
memset(have,,sizeof(have));
memset(zhis,,sizeof(zhis));
for(int i=;i<=N;i++){
G[i].clear();
zhiyinshu[i].clear();
scanf("%d",&num[i]);
have[num[i]]=i;
int tmp=num[i];
for(int j=;;j++){
if(prime[tmp]){
zhiyinshu[i].push_back(tmp);
zhis[i]++;
break;
}
if(tmp%prims[j]==){
tmp/=prims[j];
zhiyinshu[i].push_back(prims[j]);
zhis[i]++;
while(tmp%prims[j]==){
tmp/=prims[j];
zhis[i]++;
}
}
if(tmp<prims[j]) break;
}
}
for(int i=;i<=N;i++){
for(int j=;j<zhiyinshu[i].size();j++){
if(have[num[i]/zhiyinshu[i][j]]){
int u=have[num[i]/zhiyinshu[i][j]];
G[i].push_back(u);
G[u].push_back(i);
}
}
} uN=;
for(int i=;i<=N;i++){
if(zhis[i]%==){
l[uN++]=i;
}
}
printf("Case %d: %d\n",t,N-MaxMatch());
}
return ;
}

Lightoj1356的更多相关文章

  1. Lightoj-1356 Prime Independence(质因子分解)(Hopcroft-Karp优化的最大匹配)

    题意: 找出一个集合中的最大独立集,任意两数字之间不能是素数倍数的关系. 思路: 最大独立集,必然是二分图. 最大数字50w,考虑对每个数质因子分解,然后枚举所有除去一个质因子后的数是否存在,存在则建 ...

随机推荐

  1. 【Linux网络基础】上网原理流程

    1. 局域网用户上网原理 上网过程说明: 确保物理设备和线路架构准备完毕,并且线路通讯状态良好 终端设备需要获取或配置上局域网(私有地址)地址,作为局域网网络标识 当终端设备想上网时,首先确认访问的地 ...

  2. 记一次Pinpoint监控工具部署过程

    环境:Centos 7.4 X64IP:192.168.1.11 1.配置环境,先安装jdk 到Oracle官网下载安装JDK https://www.oracle.com/technetwork/j ...

  3. JS基础入门篇(十)— 数组方法

    1.join 作用: 将数组通过指定字符拼接成字符串.语法: string arr.join([separator = ',']);参数: separator可选,如果省略的话,默认为一个逗号.如果 ...

  4. C#模板编程(2): 编写C#预处理器,让模板来的再自然一点

    在<C#模板编程(1):有了泛型,为什么还需要模板?>文中,指出了C#泛型的局限性,为了突破这个局限性,我们需要模板编程.但是,C#语法以及IDE均不支持C#模板编程,怎么办呢?自己动手, ...

  5. Linked List-2

    三.编码技巧 1.遍历链表 先将head指针赋值给一个局部变量current: //return the number of nodes in a list (while-loop version) ...

  6. Codeforces Round #622 (Div. 2) 1313 A

    Tired of boring office work, Denis decided to open a fast food restaurant. On the first day he made ...

  7. 图论--LCA--在线RMQ ST

    板子测试POJ1330,一发入魂,作者是KuangBin神犇,感谢?‍ #include <cstdio> #include <cstring> #include <al ...

  8. Fiddler 介绍

    1.fiddler原理介绍 fiddler 是一个抓包工具,当浏览器访问服务器会形成一个请求,此时,fiddler就处于请求之间,当浏览器发送请求,会先经过 fiddler,然后在到服务器:当服务器有 ...

  9. 经过踩坑,搭建成功的Appium自动化测试环境

    因为最近本人准备搞app自动化,所以就搭建环境过程记录下来(主要踩过好几个坑) 期间有点烦躁,后面调整了下心态还是成功弄好了. 一.Appium环境搭建准备软件 所需要到的软件如下: 1.安装JDK1 ...

  10. 跟哥一起学python(4)- 数据类型之Number

    本节我们开始学习python的数据类型. 什么是数据类型呢?前面我们提过,所谓的编程,就是控制一系列的数据去完成我们预设的逻辑或者功能.所以,编程语言首先要定义一系列对“数据”的处理规则.这些处理规则 ...