Lightoj-1356 Prime Independence(质因子分解)(Hopcroft-Karp优化的最大匹配)
题意:
找出一个集合中的最大独立集,任意两数字之间不能是素数倍数的关系。
思路:
最大独立集,必然是二分图。
最大数字50w,考虑对每个数质因子分解,然后枚举所有除去一个质因子后的数是否存在,存在则建边,考虑到能这样建边的数一定是质因子个数奇偶不同,所以相当于按奇偶区分建立了二分图,然后求二分图最大匹配,得到最大独立集就行了。
有一点这个题数据比较大,直接匈牙利炸了,要Hopcroft-Karp优化才能过。
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <string>
#include <stack>
#include <queue>
#include <vector>
#include <map>
#define inf 0x3f3f3f3f
#define met(a,b) memset(a,b,sizeof a)
#define pb push_back
using namespace std;
typedef long long ll;
const int N = 5e4+;
int n,m,sum,res,flag;
bool mark[*N];
int pri[N],cnt;
void SP()
{
cnt=;
memset(mark,true,sizeof(mark));
mark[]=mark[]=false;
for(int i=; i<*N; i++)
{
if(mark[i])
pri[cnt++]=i;
for (int j=; (j<cnt)&&(i*pri[j]<*N); j++)
{
mark[i*pri[j]]=false;
if (i%pri[j]==)
break;
}
}
}
int pos[*N],num[N];
int f[N];
int vm[N],um[N];
bool vis[N];
vector<int>g[N];
int dx[N],dy[N],dis;
void init()
{
n=m=;
memset(pos,,sizeof(pos));
memset(f,-,sizeof(f));
memset(vm,-,sizeof(vm));
memset(um,-,sizeof(um));
for(int i=; i<=sum; i++)
g[i].clear();
}
void inserts(int u, int v)
{
g[u].push_back(v);
}
bool searchP()
{
queue<int>q;
dis=inf;
memset(dx,-,sizeof(dx));
memset(dy,-,sizeof(dy));
for(int i=; i<=sum; i++)
if(um[i]==-)
{
q.push(i);
dx[i]=;
}
while(!q.empty())
{
int u=q.front();
q.pop();
if(dx[u]>dis) break;
for(int i=; i<g[u].size(); i++)
{
int v = g[u][i];
if(dy[v]==-)
{
dy[v]=dx[u]+;
if(vm[v]==-) dis=dy[v];
else
{
dx[vm[v]]=dy[v]+;
q.push(vm[v]);
}
}
}
}
return dis!=inf;
}
bool dfs(int u)
{
for(int i=; i<g[u].size(); i++)
{
int v = g[u][i];
if(!vis[v]&&dy[v]==dx[u]+)
{
vis[v]=;
if(vm[v]!=-&&dy[v]==dis) continue;
if(vm[v]==-||dfs(vm[v]))
{
vm[v]=u;
um[u]=v;
return ;
}
}
}
return ;
}
int maxMatch()
{
int res=;
while(searchP())
{
memset(vis,,sizeof(vis));
for(int i=; i<=sum; i++)
if(um[i]==-&&dfs(i)) res++;
}
return res;
}
int tmp[N],now,all;
void solve(int t,int tot)
{
now = all = ;
int tt=t;
for(int i=; i<cnt&&pri[i]*pri[i]<=tt; i++)
{
if(tt%pri[i]==)
tmp[now++] = pri[i];
while(tt%pri[i]==)
tt/=pri[i],all++;
}
if(tt>)tmp[now++] = tt, all++;
f[tot]=&all;
if(f[tot])n++;
else m++;
for(int i=; i<now; i++)
{
int x=t/tmp[i];
if(pos[x])
{
if(!f[tot])inserts(tot,pos[x]);
else inserts(pos[x],tot);
}
}
}
int main()
{
int i,j,k,cas,T,t,x,y,z;
SP();
scanf("%d",&T);
cas=;
while(T--)
{
scanf("%d",&sum);
init();
for(i=; i<=sum; i++)
scanf("%d",&num[i]);
for(i=; i<=sum; i++)
pos[num[i]] = i;
for(i=; i<=sum; i++)
solve(num[i],i);
printf("Case %d: %d\n",++cas,sum-maxMatch());
}
return ;
}
Lightoj-1356 Prime Independence(质因子分解)(Hopcroft-Karp优化的最大匹配)的更多相关文章
- LightOJ 1356 Prime Independence(质因数分解+最大独立集+Hopcroft-Carp)
http://lightoj.com/login_main.php?url=volume_showproblem.php?problem=1356 题意: 给出n个数,问最多能选几个数,使得该集合中的 ...
- LightOJ - 1356 Prime Independence (数论+二分图匹配)
题意:有N个数的集合,其中选出若干个数组成一个子集,要求这个子集中的任意两个数a,b都不能通过a=k*b得到,其中k是一个素数.求这个子集最大的size. 分析:集合中任意两数的关系是二者之间是否之差 ...
- LightOJ 1356 Prime Independence 二分图最大独立集,HK算法
这个题唯一需要说的就是普通的匈牙利算法是O(nm)的,过不了 然后HK算法可以O(n^0.5m),这个算法可以每次找很多同样长度的最短增广路 分析见:http://www.hardbird.net/l ...
- LightOJ - 1356 Prime Independence (二分图 最大独立集 素数打表)
题意: 给你一个集合,让你从这个集合中挑选出几个数,使得这几个数中任意两个数相除后的值不能为素数 即挑选出来的这几个数不能互相冲突 最大独立集 = 所有点数 - 最大匹配数 呵..呵...原先用的二维 ...
- P2043 质因子分解
P2043 质因子分解 题目描述 对N!进行质因子分解. 输入输出格式 输入格式: 输入数据仅有一行包含一个正整数N,N<=10000. 输出格式: 输出数据包含若干行,每行两个正整数p,a,中 ...
- P2043 质因子分解(阶乘的质因数分解)
P2043 质因子分解 对$n!$进行质因数分解的一种高效算法 首先,筛出$<=n$的素数 蓝后,对$n$反复除以$prime$,同时$cnt+=n/prime$ $n!$中含有该$prime$ ...
- LightOJ1336 Sigma Function —— 质因子分解、约数和为偶数
题目链接:https://vjudge.net/problem/LightOJ-1336 1336 - Sigma Function PDF (English) Statistics Forum ...
- hdu2389二分图之Hopcroft Karp算法
You're giving a party in the garden of your villa by the sea. The party is a huge success, and every ...
- BZOJ 1485: [HNOI2009]有趣的数列 [Catalan数 质因子分解]
1485: [HNOI2009]有趣的数列 Description 我们称一个长度为2n的数列是有趣的,当且仅当该数列满足以下三个条件: (1)它是从1到2n共2n个整数的一个排列{ai}: (2)所 ...
随机推荐
- [LOJ#2553][CTSC2018]暴力写挂
[LOJ#2553][CTSC2018]暴力写挂 试题描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = ...
- [Leetcode] The minimum depth of binary tree二叉树的最小深度
Given a binary tree, find its minimum depth. The minimum depth is the number of nodes along the shor ...
- LinuxUnix time时间戳的处理转换函数
Linux/Unix time时间戳的处理转换函数 linux下的时间函数 我们在编程中可能会经常用到时间,比如取得系统的时间(获取系统的年.月.日.时.分.秒,星期等),或者是隔一段时间去做某事,那 ...
- 用原生JavaScript做个简单的回到顶部
很多网页在下方都会放置一个“返回顶部”按钮,尤其是页面底部没有导航的网页,这样可以帮助访客重新找到导航或者重温一遍广告(想得真美).随着近几年来 JavaScript 的应用日渐广泛,滑动效果无处不在 ...
- 两个数组的交集 II [ LeetCode - 350 ]
原题地址:https://leetcode-cn.com/problems/intersection-of-two-arrays-ii/description/ 给定两个数组,写一个方法来计算 ...
- GTK+与MFC不完全对比
转载自:http://tech.ddvip.com/2007-11/119640973738229.html 1. 两者都是基于面向对象设计的.尽管MFC是用C++写的,而GTK+是用C写的,但思想都 ...
- nodejs是用来做什么的?
有些人说“这是一种通过javascript语言开发web服务端的东西”.更直白的可以理解为:node.js有非阻se塞,事件驱动/O等特性,从而让高并发(high concurrency)在的轮询和c ...
- HDU 5881--Tea 思维规律
感谢http://blog.csdn.net/black_miracle/article/details/52567718 题意:有一壶水, 体积在 L和 R之间, 有两个杯子, 你要把水倒到两个杯子 ...
- 【BZOJ】1770 [Usaco2009 Nov]lights 燈
[算法]高斯消元-异或方程组 [题解]良心简中题意 首先开关顺序没有意义. 然后就是每个点选或不选使得最后得到全部灯开启. 也就是我们需要一种确定的方案,这种方案使每盏灯都是开启的. 异或中1可以完美 ...
- Invalidate()(转)
原文转自 http://m.blog.csdn.net/blog/piaopiaopiaopiaopiao/41521211 使用Invalidate(TRUE)函数时,它会向消息队列中添加了WM_E ...