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 ...
随机推荐
- 第二百二十八节,jQuery EasyUI,TreeGrid(树形表格)组件
jQuery EasyUI,TreeGrid(树形表格)组件 学习要点: 1.加载方式 2.属性列表 3.事件列表 4.方法列表 本节课重点了解 EasyUI 中 TreeGrid(树形表格)组件的使 ...
- 【BZOJ】1857: [Scoi2010]传送带(三分)
http://www.lydsy.com/JudgeOnline/problem.php?id=1857 好神奇的三分.. 第一次写三分啊sad..看了题解啊题解QAQ 首先发现无论怎么走一定是在AB ...
- 【BZOJ】3296: [USACO2011 Open] Learning Languages(tarjan)
http://www.lydsy.com/JudgeOnline/problem.php?id=3296 显然,每群能交流的群是个强联通块 然后求出scc的数量,答案就是scc-1 #include ...
- 蓝桥杯 第三届C/C++预赛真题(9) 夺冠概率(手工计算概率)
足球比赛具有一定程度的偶然性,弱队也有战胜强队的可能. 假设有甲.乙.丙.丁四个球队.根据他们过去比赛的成绩,得出每个队与另一个队对阵时取胜的概率表: 甲 乙 丙 丁 甲 - 0.1 0.3 0.5乙 ...
- 【Debian】install
n年前的报废台式机实在不能忍受xp的速度,果断装Linux近期家里的小本装了Ubuntu14.04 ,实在不习惯最新的图形界面.装个debian试试吧. 1.专门弄一个空白分区2.官网下载debian ...
- cygwin下编译zlib源代码
本文介绍在cygwin下编译zlib源代码的方法步骤,这个过程尽管简单,但还是有一些须要注意的地方. zlib源代码下载地址: http://www.zlib.net/ 下载后.解压就会生成zlib- ...
- Poj1426
Find The Multiple Time Limit: 1000MS Memory Limit: 10000K Total Submissions: 25721 Accepted: 106 ...
- iOS 遍历控件
NSArray *subviews = [_bgImageView subviews]; for (id objInput in subviews) { if ([objInput isKindOfC ...
- group_concat 多对多关联, 统计分组数据, 结果拼接到一个字段
统计用户所有的角色, 结果: 1 张三 普通用户,管理员,XXX 2 李四 普通用户, XXX select ur.user_id,u.login_name,GROUP_CONCAT ...
- bash短路径显示
修改.bashrc文件vim 打开.bashrc文件,找到如下这行,有两个,都修改一下: PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ ' 将上面 ...