Lightoj-1356 Prime Independence(质因子分解&&二分图最大独立集)
2016-04-06 19:12
465 查看
题目:
http://lightoj.com/volume_showproblem.php?problem=1356题意:
找出一个集合中的最大独立集,任意两数字之间不能是素数倍数的关系。思路:
最大独立集,必然是二分图。最大数字50w,考虑对每个数质因子分解,然后枚举所有除去一个质因子后的数是否存在,存在则建边,考虑到能这样建边的数一定是质因子个数奇偶不同,所以相当于按奇偶区分建立了二分图,然后求二分图最大匹配,得到最大独立集就行了。
有一点这个题数据比较大,直接匈牙利炸了,要Hopcroft-Karp优化才能过。
代码:
//kopyh #include <bits/stdc++.h> #define INF 0x3f3f3f3f #define MOD 1000000007 #define N 51234 using namespace std; int n,m,sum,res,flag; bool mark[10*N]; int pri ,cnt; void SP() { cnt=0; memset(mark,true,sizeof(mark)); mark[0]=mark[1]=false; for(int i=2;i<10*N;i++) { if(mark[i]) pri[cnt++]=i; for (int j=0;(j<cnt)&&(i*pri[j]<10*N);j++) { mark[i*pri[j]]=false; if (i%pri[j]==0) break; } } } int pos[10*N],num ; int f ; int vm ,um ; bool vis ; vector<int>g ; int dx ,dy ,dis; void init() { n=m=0; memset(pos,0,sizeof(pos)); memset(f,-1,sizeof(f)); memset(vm,-1,sizeof(vm)); memset(um,-1,sizeof(um)); for(int i=0;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,-1,sizeof(dx)); memset(dy,-1,sizeof(dy)); for(int i=1;i<=sum;i++) if(um[i]==-1) { q.push(i); dx[i]=0; } while(!q.empty()) { int u=q.front();q.pop(); if(dx[u]>dis) break; for(int i=0;i<g[u].size();i++) { int v = g[u][i]; if(dy[v]==-1) { dy[v]=dx[u]+1; if(vm[v]==-1) dis=dy[v]; else { dx[vm[v]]=dy[v]+1; q.push(vm[v]); } } } } return dis!=INF; } bool dfs(int u) { for(int i=0;i<g[u].size();i++) { int v = g[u][i]; if(!vis[v]&&dy[v]==dx[u]+1) { vis[v]=1; if(vm[v]!=-1&&dy[v]==dis) continue; if(vm[v]==-1||dfs(vm[v])) { vm[v]=u;um[u]=v; return 1; } } } return 0; } int maxMatch() { int res=0; while(searchP()) { memset(vis,0,sizeof(vis)); for(int i=1;i<=sum;i++) if(um[i]==-1&&dfs(i)) res++; } return res; } int tmp ,now,all; void solve(int t,int tot) { now = all = 0; int tt=t; for(int i=0;i<cnt&&pri[i]*pri[i]<=tt;i++) { if(tt%pri[i]==0) tmp[now++] = pri[i]; while(tt%pri[i]==0) tt/=pri[i],all++; } if(tt>1)tmp[now++] = tt, all++; f[tot]=1&all; if(f[tot])n++; else m++; for(int i=0;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; #ifndef ONLINE_JUDGE freopen("test.txt","r",stdin); #endif SP(); scanf("%d",&T); cas=0; while(T--) { scanf("%d",&sum); init(); for(i=1;i<=sum;i++) scanf("%d",&num[i]); for(i=1;i<=sum;i++) pos[num[i]] = i; for(i=1;i<=sum;i++) solve(num[i],i); printf("Case %d: %d\n",++cas,sum-maxMatch()); } return 0; }
相关文章推荐
- 四则运算《安卓版》04
- [kuangbin带你飞]专题十七 AC自动机
- 《机电传动控制》----学习笔记六
- 整数数组中最大子数组求和03
- 通过GET方式传递数据给服务器
- Bookmarks
- OA项目实战学习(3)——实现岗位管理增删改查
- bzoj 2502: 清理雪道
- python小模块---zipfile
- IOS-使用XCODE自带的单元测试UnitTest
- 中国移动 全球通、 动感地带、神州行 的区别
- [kuangbin带你飞]专题十六 KMP & 扩展KMP & Manacher
- Rotate Array 带测试版
- JavaFX E4 RCP创建Model Fragment后报错:No application id has been found.
- AngularJS之基础-5 路由(定义路由、使用路由)、自定义指令(Directive)
- 8080port is already in use. cmd结束进程也拒绝访问,ntsd也不管用(win8)
- 零碎一学
- (第10讲)插入式排序
- [kuangbin带你飞]专题十五 数位DP
- 学习进度05