WuliWuliiii
凤兮凤兮归故乡 遨游四海求其凰

  题意:从N个数中找出一个最大子集,满足这个集合中的任意两个数都不存在质数倍的关系,就匹配1和3就是质数(3)倍,然而1和4就不是质数倍。

  分析:很明显的,从联通集合中求出一个最大独立集,就是独立集问题了,再一分析,不存在“x乘以(质数乘以质数)=y”这样的情况,所以可以看出,这是一个二分图。那么问题变成了求二分图的最大独立集这样的一个问题了。于是,再一分析,我们可以发现这a[i]各不相同,所以我们直接进行存位置,然后链接边,就可以了,这里用HK来跑,用匈牙利的话,是会TLE的。

  当然,这里犯了个大错,就是当求质数的时候,我们可以用x的质数倍存在与否而不是x的质因子除去后的数存在与否,会比较的方便。

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cmath>
  4 #include <string>
  5 #include <cstring>
  6 #include <algorithm>
  7 #include <limits>
  8 #include <vector>
  9 #include <stack>
 10 #include <queue>
 11 #include <set>
 12 #include <map>
 13 #include <bitset>
 14 #include <unordered_map>
 15 #include <unordered_set>
 16 #define lowbit(x) ( x&(-x) )
 17 #define pi 3.141592653589793
 18 #define e 2.718281828459045
 19 #define INF 0x3f3f3f3f
 20 #define HalF (l + r)>>1
 21 #define lsn rt<<1
 22 #define rsn rt<<1|1
 23 #define Lson lsn, l, mid
 24 #define Rson rsn, mid+1, r
 25 #define QL Lson, ql, qr
 26 #define QR Rson, ql, qr
 27 #define myself rt, l, r
 28 #define pii pair<int, int>
 29 #define MP(a, b) make_pair(a, b)
 30 using namespace std;
 31 typedef unsigned long long ull;
 32 typedef unsigned int uit;
 33 typedef long long ll;
 34 const int maxN = 4e4 + 7;
 35 vector<int> Prime;
 36 bool vis[500005] = {false};
 37 void Prime_Init()
 38 {
 39     for(int i = 2; i <= 500000; i ++)
 40     {
 41         if(!vis[i])
 42         {
 43             Prime.push_back(i);
 44             for(int j = i * 2; j <= 500000; j += i) vis[j] = true;
 45         }
 46     }
 47 }
 48 int N, a[maxN], pos[500005];
 49 int head[maxN], cnt;
 50 struct Eddge
 51 {
 52     int nex, to;
 53     Eddge(int a=-1, int b=0):nex(a), to(b) {}
 54 } edge[1000006];
 55 inline void addEddge(int u, int v)
 56 {
 57     edge[cnt] = Eddge(head[u], v);
 58     head[u] = cnt ++;
 59 }
 60 inline void _add(int u, int v) { addEddge(u, v); addEddge(v, u); }
 61 void init()
 62 {
 63     cnt = 0;
 64     for(int i = 1; i <= N; i ++) head[i] = -1;
 65 }
 66 namespace HK
 67 {
 68     int mx[maxN], my[maxN];
 69     int dx[maxN], dy[maxN], dis;
 70     bool vis[maxN];
 71     bool searchP()
 72     {
 73         queue<int> Q;
 74         dis = INF;
 75         for(int i = 1; i <= N; i ++) dx[i] = -1;
 76         for(int i = 1; i <= N; i ++) dy[i] = -1;
 77         for(int i = 1; i <= N; i ++)
 78         {
 79             if(mx[i] == -1)
 80             {
 81                 Q.push(i);
 82                 dx[i] = 0;
 83             }
 84         }
 85         while(!Q.empty())
 86         {
 87             int u = Q.front(); Q.pop();
 88             if(dx[u] > dis) break;
 89             for(int i = head[u], v; ~i; i = edge[i].nex)
 90             {
 91                 v = edge[i].to;
 92                 if(dy[v] == -1)
 93                 {
 94                     dy[v] = dx[u] + 1;
 95                     if(my[v] == -1) dis = dy[v];
 96                     else
 97                     {
 98                         dx[my[v]] = dy[v] + 1;
 99                         Q.push(my[v]);
100                     }
101                 }
102             }
103         }
104         return dis != INF;
105     }
106     bool dfs(int u)
107     {
108         for(int i = head[u], v; ~i; i = edge[i].nex)
109         {
110             v = edge[i].to;
111             if(!vis[v] && dy[v] == dx[u] + 1)
112             {
113                 vis[v] = 1;
114                 if(my[v] != -1 && dy[v] == dis) continue;
115                 if(my[v] == -1 || dfs(my[v]))
116                 {
117                     my[v] = u;
118                     mx[u] = v;
119                     return 1;
120                 }
121             }
122         }
123         return 0;
124     }
125     int MaxMatch()
126     {
127         int res = 0;
128         for(int i = 1; i <= N; i ++) mx[i] = -1;
129         for(int i = 1; i <= N; i ++) my[i] = -1;
130         while(searchP())
131         {
132             for(int i = 1; i <= N; i ++) vis[i] = false;
133             for(int i = 1; i <= N; i ++)
134             {
135                 if(mx[i] == -1 && dfs(i)) res ++;
136             }
137         }
138         return res;
139     }
140 }
141 using namespace HK;
142 int main()
143 {
144     Prime_Init();
145     int T; scanf("%d", &T);
146     for(int Cas = 1; Cas <= T; Cas ++)
147     {
148         scanf("%d", &N);
149         int maxx = 1;
150         for(int i = 1; i <= N; i ++) { scanf("%d", &a[i]); maxx = max(maxx, a[i]); }
151         for(int i = 1; i <= N; i ++) pos[a[i]] = i;
152         init(); int len = (int)Prime.size();
153         for(int i = 1, x; i <= N; i ++)
154         {
155             x = a[i];
156             for(int j = 0, v; j < len && Prime[j] * a[i] <= maxx; j ++)
157             {
158                 v = pos[Prime[j] * a[i]];
159                 if(!v) continue;
160                 _add(i, v);
161             }
162         }
163         printf("Case %d: %d\n", Cas, N - MaxMatch() / 2);
164         for(int i = 1; i <= N; i ++) pos[a[i]] = 0;
165     }
166     return 0;
167 }

 

posted on 2021-01-21 19:33  唔哩Wulili  阅读(69)  评论(0编辑  收藏  举报