leetcode

题意:给定一组数,任意两个不是互素的数能连接在一起,问最终最大的一个连接部件的元素个数是多少。
思路:预处理筛素数得到所有小于等于数组最大值的素数。然后用并查集,将该数的质因数放到同一个集合里面,首先默认小的质因数会是根,所以接下来会把较大的质因数并入较小的质因数上面去,而在查询方面,合并前会检查是否合并过,合并过的话,那么就直接数量加一即可,若没有合并过,两个集合的数目加起来,然后较大的质因数的根为较小的质因数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
class 
{
private:
int find(const vector<int> &pre, int x)
{
while (pre[x] != -1)
{
x = pre[x];
}
return x;
}
void unionx(vector<int> &pre, vector<int> &cnt, int x, int y)
{
int fx = find(pre, x), fy = find(pre, y);
if (fx != fy)
{
pre[fy] = fx;
cnt[fx] += cnt[fy];
}
}

public:
int largestComponentSize(vector<int> &A)
{
int maxi = (*max_element(A.begin(), A.end())) + 5;
vector<bool> isPrime(maxi, true);
vector<int> primes;
for (int i = 2; i < maxi; ++i)
{
if (!isPrime[i])
continue;
primes.emplace_back(i);
for (int j = i + i; j < maxi; j += i)
{
isPrime[j] = false;
}
}


vector<int> pre(maxi, -1), cnt(maxi, 0), visited(maxi, -1);


for (auto a : A)
{
int i = 0, p = -1;
if (visited[a] != -1) {
cnt[visited[a]] += 1;
}
while (primes[i] <= a)
{
if (isPrime[a]) {
if (p == -1)
{
int temp = find(pre, a);
visited[a] = temp;
cnt[temp] += 1;
}
else
{
unionx(pre, cnt, p, a);
}
break;
}
if (a % primes[i] == 0)
{
if (p == -1)
{
p = primes[i];
int temp = find(pre, p);
visited[a] = temp;
cnt[temp] += 1;
}
else
{
unionx(pre, cnt, p, primes[i]);
}
while (a % primes[i] == 0)
a /= primes[i];
}
i++;
}
}
int ans = 1;
for (auto a : cnt)
{
ans = max(ans, a);
}
return ans;
}
};