F - Prime Independence
Problem Description
A set of integers is called prime independent if none of its member is a prime multiple of another member. An integer a is said to be a prime multiple of b if,
a = b x k (where k is a prime [1])
So, 6 is a prime multiple of 2, but 8 is not. And for example, {2, 8, 17} is prime independent but {2, 8, 16} or {3, 6} are not.
Now, given a set of distinct positive integers, calculate the largest prime independent subset.
Input
Input starts with an integer T (≤ 20), denoting the number of test cases.
Each case starts with an integer N (1 ≤ N ≤ 40000) denoting the size of the set. Next line contains N integers separated by a single space. Each of these N integers are distinct and between 1 and 500000 inclusive.
Output
Sample Input
3 5 2 4 8 16 32 5 2 3 4 6 9 3 1 2 3
Sample Output
Case 1: 3 Case 2: 3 Case 3: 2
Hint
An integer is said to be a prime if it's divisible by exactly two distinct integers. First few prime numbers are 2, 3, 5, 7, 11, 13, ...
Dataset is huge, use faster I/O methods.
1 #include <stdio.h> 2 #include <queue> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 #include <vector> 7 #include <map> 8 #include <set> 9 #include <ctime> 10 #include <cmath> 11 #include <cctype> 12 #include <iostream> 13 using namespace std; 14 typedef long long LL; 15 const int N=5*1e5+10; 16 const int INF=0x3f3f3f3f; 17 const int maxn=40010; 18 int cas=1,T; 19 int id[N]; 20 struct maxMacth 21 { 22 int n; 23 int vm[N],um[N]; 24 bool vis[N]; 25 vector<int>g[N]; 26 int dx[N],dy[N],dis; 27 void init(int num) 28 { 29 n=num; 30 memset(vm,-1,sizeof(vm)); 31 memset(um,-1,sizeof(um)); 32 for(int i=0;i<=n;i++) 33 g[i].clear(); 34 } 35 void inserts(int u, int v) 36 { 37 g[u].push_back(v); 38 } 39 bool searchP() 40 { 41 queue<int>q; 42 dis=INF; 43 memset(dx,-1,sizeof(dx)); 44 memset(dy,-1,sizeof(dy)); 45 for(int i=1;i<=n;i++) 46 if(um[i]==-1) 47 { 48 q.push(i); 49 dx[i]=0; 50 } 51 while(!q.empty()) 52 { 53 int u=q.front();q.pop(); 54 if(dx[u]>dis) break; 55 for(int i=0;i<g[u].size();i++) 56 { 57 int v = g[u][i]; 58 if(dy[v]==-1) 59 { 60 dy[v]=dx[u]+1; 61 if(vm[v]==-1) dis=dy[v]; 62 else 63 { 64 dx[vm[v]]=dy[v]+1; 65 q.push(vm[v]); 66 } 67 } 68 } 69 } 70 return dis!=INF; 71 } 72 bool dfs(int u) 73 { 74 for(int i=0;i<g[u].size();i++) 75 { 76 int v = g[u][i]; 77 if(!vis[v]&&dy[v]==dx[u]+1) 78 { 79 vis[v]=1; 80 if(vm[v]!=-1&&dy[v]==dis) continue; 81 if(vm[v]==-1||dfs(vm[v])) 82 { 83 vm[v]=u;um[u]=v; 84 return 1; 85 } 86 } 87 } 88 return 0; 89 } 90 int maxMatch() 91 { 92 int res=0; 93 while(searchP()) 94 { 95 memset(vis,0,sizeof(vis)); 96 for(int i=1;i<=n;i++) 97 if(um[i]==-1&&dfs(i)) res++; 98 } 99 return res; 100 } 101 }MM; 102 int pn,p[N],vis[N],e[N]; 103 void init() 104 { 105 memset(vis,0,sizeof(vis)); 106 memset(e,0,sizeof(e)); 107 pn=0; 108 for(int i=2;i<N;i++) if(!vis[i]) 109 { 110 p[pn++]=i; 111 for(int j=i;j<N;j+=i) 112 { 113 vis[j]=1; 114 int x=j; 115 while(x%i==0) x/=i,e[j]++; 116 } 117 } 118 } 119 int main() 120 { 121 // freopen("1.in","r",stdin); 122 // freopen("1.out","w",stdout); 123 init(); 124 scanf("%d",&T); 125 while(T--) 126 { 127 int n; 128 scanf("%d",&n); 129 memset(id,0,sizeof(id)); 130 for(int i=1,x;i<=n;i++) scanf("%d",&x),id[x]=i; 131 MM.init(n); 132 for(int i=1;i<N;i++) if(id[i]) 133 { 134 for(int j=0;i*p[j]<N && j<pn;j++) if(id[i*p[j]]) 135 { 136 if(e[i]&1) 137 MM.g[id[i]].push_back(id[i*p[j]]); 138 else 139 MM.g[id[i*p[j]]].push_back(id[i]); 140 } 141 } 142 printf("Case %d: %d ",cas++,n-MM.maxMatch()); 143 // printf("Case %d: %d ",cas++,n-MM.maxMatch()/2); 144 // cerr<<clock()<<"ms "; 145 } 146 return 0; 147 }
题解:
用筛法将满足a×p=b(p为质数)的a,b建一条边(注意方向),然后跑二分图最大匹配,也可以直接建两条边,然后结果除以二
答案为:点数-最大匹配