LightOJ - 1356 Prime Independence (数论+二分图匹配)
题意:有N个数的集合,其中选出若干个数组成一个子集,要求这个子集中的任意两个数a,b都不能通过a=k*b得到,其中k是一个素数。求这个子集最大的size。
分析:集合中任意两数的关系是二者之间是否之差一个质因子,那么对于这种关系,本题要求的是N个点的最大独立集。|最大独立集| = 点数 - |二分图最大匹配|。
想到这步之后,就是如何建图的问题。
先预处理筛出一定范围内的素数。对于每个集合内的数a,检查其除去一个质因子后得到的数at是否在集合中出现,若出现则将a到at和at到a建边。
因为是双向建边,所以得到的最大匹配数是两倍,除以2即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int MAXN = ;
const int MAXM = *;
const int INF = 0x3f3f3f3f;
int N;
struct Node{
int x,y;
}p[MAXN],it[MAXN];
int v[MAXN]; struct Edge{
int v;
int next;
}edge[MAXM]; int nx, ny;
int cnt;
int t;
int dis; int first[MAXN];
int xlink[MAXN], ylink[MAXN];
/*xlink[i]表示左集合顶点所匹配的右集合顶点序号,ylink[i]表示右集合i顶点匹配到的左集合顶点序号。*/
int dx[MAXN], dy[MAXN];
/*dx[i]表示左集合i顶点的距离编号,dy[i]表示右集合i顶点的距离编号*/
int vis[MAXN]; //寻找增广路的标记数组
void init(){
cnt = ;
memset(first, -, sizeof(first));
memset(xlink, -, sizeof(xlink));
memset(ylink, -, sizeof(ylink));
} void AddEdge(int u, int v){
edge[cnt].v = v;
edge[cnt].next = first[u], first[u] = cnt++;
} int bfs()
{
queue<int> q;
dis = INF;
memset(dx, -, sizeof(dx));
memset(dy, -, sizeof(dy));
for(int i = ; i <= nx; i++){
if(xlink[i] == -){
q.push(i);
dx[i] = ;
}
}
while(!q.empty()){
int u = q.front(); q.pop();
if(dx[u] > dis) break;
for(int e = first[u]; e != -; e = edge[e].next){
int v = edge[e].v;
if(dy[v] == -){
dy[v] = dx[u] + ;
if(ylink[v] == -) dis = dy[v];
else{
dx[ylink[v]] = dy[v]+;
q.push(ylink[v]);
}
}
}
}
return dis != INF;
} int find(int u){
for(int e = first[u]; e != -; e = edge[e].next){
int v = edge[e].v;
if(!vis[v] && dy[v] == dx[u]+){
vis[v] = ;
if(ylink[v] != - && dy[v] == dis) continue;
if(ylink[v] == - || find(ylink[v])){
xlink[u] = v, ylink[v] = u;
return ;
}
}
}
return ;
} int MaxMatch()
{
int ans = ;
while(bfs()){
memset(vis, , sizeof(vis));
for(int i = ; i <= nx; i++)
if(xlink[i] == -)
ans += find(i);
}
return ans;
} const int MAXV = ;
int prime[MAXV];
bool notprime[MAXV*];
void pre()
{
int up = MAXV *;
memset(notprime,,sizeof(notprime));
notprime[] = notprime[] = true;
memset(prime,,sizeof(prime));
for(int i=;i<up;++i){
if(!notprime[i]) prime[++prime[]] = i;
for(int j= ; j<=prime[] && prime[j] <= up / i ;++j){
notprime[prime[j]*i] = true;
if(i%prime[j]==) break;
}
}
} int pos[MAXV*];
int num[MAXV];
int fac[MAXV];
bool jo[MAXV*];
void ADD(int num,int pt){
int sum = ,all=;
int tmp = num;
for(int i=;prime[i]*prime[i]<=tmp;i++){
if(tmp%prime[i]==){
fac[sum++] = prime[i];
while(tmp%prime[i]==) tmp/=prime[i],all++;
}
}
if(tmp>) fac[sum++] = tmp,all++;
for(int i=;i<sum;++i){
int x = num/fac[i];
if(pos[x]){
AddEdge(pt,pos[x]);
AddEdge(pos[x],pt);
}
}
} int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt","r",stdin);
freopen("out.txt","w",stdout);
#endif
pre();
int T,cas=; scanf("%d",&T);
while(T--){
int N; scanf("%d",&N);
init();
memset(pos,,sizeof(pos));
for(int i=;i<=N;++i){
scanf("%d",&num[i]);
pos[num[i]] = i;
}
nx = ny =;
for(int i=;i<=N;++i){
ADD(num[i],i);
}
nx = ny = N;
int res= N - MaxMatch()/;
printf("Case %d: %d\n",cas++,res);
}
return ;
}
LightOJ - 1356 Prime Independence (数论+二分图匹配)的更多相关文章
- LightOJ 1356 Prime Independence 二分图最大独立集,HK算法
这个题唯一需要说的就是普通的匈牙利算法是O(nm)的,过不了 然后HK算法可以O(n^0.5m),这个算法可以每次找很多同样长度的最短增广路 分析见:http://www.hardbird.net/l ...
- LightOJ - 1356 Prime Independence (二分图 最大独立集 素数打表)
题意: 给你一个集合,让你从这个集合中挑选出几个数,使得这几个数中任意两个数相除后的值不能为素数 即挑选出来的这几个数不能互相冲突 最大独立集 = 所有点数 - 最大匹配数 呵..呵...原先用的二维 ...
- LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)
http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1356 题意: 给出n个数,问最多能选几个数,使得该集合中的 ...
- HDU 5938 Kingdom of Obsession(数论 + 二分图匹配)
题意: 给定S,N,把S+1,S+2,...S+N这N个数填到1,2,...,N里,要求X只能填到X的因子的位置.(即X%Y=0,那么X才能放在Y位置) 问是否能够放满. 分析:经过小队的分析得出的结 ...
- 【ARC080F】Prime Flip 差分+二分图匹配
Description 有无穷个硬币,初始有n个正面向上,其余均正面向下. 你每次可以选择一个奇质数p,并将连续p个硬币都翻转. 问最小操作次数使得所有硬币均正面向下. Input 第一行 ...
- csu 1552(米勒拉宾素数测试+二分图匹配)
1552: Friends Time Limit: 3 Sec Memory Limit: 256 MBSubmit: 723 Solved: 198[Submit][Status][Web Bo ...
- zoj3988 二分图匹配
给一个数组,对于每两个数加起来为素数那么就是一个集合,求不超过k个集合的最多数是多少 解法:二分图匹配,先打素数筛,预处理边集,匹配完之后分两种情况k>匹配数,那么可以直接输出匹配数*2,否则可 ...
- Help Hanzo (LightOJ - 1197) 【简单数论】【筛区间质数】
Help Hanzo (LightOJ - 1197) [简单数论][筛区间质数] 标签: 入门讲座题解 数论 题目描述 Amakusa, the evil spiritual leader has ...
- CodeFroces New Assignment 二分图匹配
There is a class consisting of n students, in which each one has a number representing his/her perso ...
随机推荐
- struts中如何实现国际化,涉及哪些文件?
struts中如何实现国际化,涉及哪些文件? 解答:“国际化”是指一个应用程序在运行时能够根据客户端请求所来自的国家/地区.语言的不同而显示不同的用户界面.Struts框架通过使用<bean:m ...
- 组件(Conponent)是图形用户界面最基本的部分
组件(Conponent)是图形用户界面最基本的部分,也称为构件 ,是可以以图形化的方式显示在屏幕上,并能与用户进行交互的对象,例如一个按钮,一个标签等. 组件不能独立地显示出来,必须将其放在一定的容 ...
- CopyOnWriteArrayList分析
ArrayList是比较常用的一个可变大小的数组集合,但是是不能同步的.如果多个线程同时访问一个ArrayList实例,其中至少一个线程从结构上修改了列表,那么它必须保持外部同步.一般通过加锁对象进行 ...
- 使用ghost硬盘对拷备份系统
公司有台server装了OA系统.要备份数据.同一时候假设系统出错之后可以及时回复.所以有买了块同型号硬盘. 用ghost的硬盘对拷功能,将原硬盘的系统和数据拷到新硬盘上.新硬盘挂到server上.当 ...
- 57、Design Support Library 介绍及环境搭建
一.Material Design几个要素 扁平化.简洁: 水波反馈: 良好体验的过渡动画: 材料空间位置的直观变化: 二.Android Studio配置 在 build.gradle 文件中加入, ...
- leetcode 326 Power of Three (python)
原题: Given an integer, write a function to determine if it is a power of three. Follow up: Could you ...
- 【BZOJ3673/3674】可持久化并查集/可持久化并查集加强版 可持久化线段树
[BZOJ3674]可持久化并查集加强版 Description Description:自从zkysb出了可持久化并查集后……hzwer:乱写能AC,暴力踩标程KuribohG:我不路径压缩就过了! ...
- mvn命令上传jar
开发过程中涉及到下载第三SDK包,而本身项目是基于gradle的,所以为了项目中使用sdk包,需要将包加入到自己的仓库 1.利用nexus创建自己的第三方库thirdparty 类型hosted 2. ...
- iOS开发——生命周期
为了处理好应用程序的挂起.暂停等情况下的数据保存,或对应添加所需处理,我们必须了解ios生命周期. 但是不要去背去记,做个实验就好. - (BOOL)application:(UIApplicatio ...
- Converts Internet addresses to Internet numbers. ip2long long2ip
http://php.net/manual/en/function.long2ip.phpPHP: ip2long - Manual http://php.net/manual/en/function ...