### 952. Largest Component Size by Common Factor

题目:
https://leetcode.com/problems/largest-component-size-by-common-factor/

难度:
Hard

题意：

1. 给n个数
2. 将n个数设定为n个节点，如果两个数之间的最大公约数大于1，则连边
3. 求图的最大联通分量的大小

思路：

- n的数据量高达2w，如果两两节点计算最大公约数，复杂度是o(n^2logn)
- 我们可以使用素数筛法来取出需要两两画线的数列，比如：取出被2整除的数，被3整除的数。。。
- 求图的最大联通分量可以用并查集来做
- 过程是这样的
  - 枚举所有的素数
  - 假设当前枚举的素数是i
  - 从n个数中取出所有能被i整除的数
  - 假设有m个数，那么第1个数跟第m-1个数都跟第0个数做下合并
  - 枚举结束后，求最大的集合的大小
- 素数筛法的复杂度是o(nlogn)，这里需要做下优化，如果枚举每个素数都得从n个数寻找能被它整除的数，复杂度还是o(nk)，k是素数的个数，但如果我们把n个数映射到1-100000的数组中，就可以套用素数筛法了

解法：

```c++
bool isPrime[100100];
bool hasValue[100100];
int p[100100];
int size[100100];
class Solution {
public:
    bool inited = false;
    
    void init() {
        memset(isPrime, true, sizeof(isPrime));
        for (int i = 2;i <= 100000;i++) {
            if (!isPrime[i]) {
                continue;
            }
            for (int j = i + i;j <= 100000;j += i) {
                isPrime[j] = false;
            }
        }
    }
    
    int find_set(int x) {
        vector<int> temp;
        while (p[x] != x) {
            temp.push_back(x);
            x = p[x];
        }
        for (int i = 0;i < temp.size();i++) {
            p[temp[i]] = x;
        }
        return x;
    }
    
    void union_set(int x, int y) {
        x = find_set(x);
        y = find_set(y);
        if (x == y) {
            return;
        }
        p[x] = y;
        size[y] += size[x];
    }
    
    vector<int> find(int prime) {
        vector<int> ret;
        for (int i = prime;i <= 100000;i += prime) {
            if (hasValue[i]) {
                ret.push_back(i);
            }
        }
        return ret;
    }
    
    int largestComponentSize(vector<int>& A) {
        if (!inited) {
            init();
            inited = true;
        }
        
        memset(hasValue, false, sizeof(hasValue));
        for (int i = 0;i < A.size();i++) {
            hasValue[A[i]] = true;
        }
        for (int i = 0;i <= 100000;i++) {
            p[i] = i;
            size[i] = 1;
        }
        for (int i = 2;i <= 100000;i++) {
            if(isPrime[i]) {
                vector<int> temp = find(i);
                
                if (temp.size() == 0){
                    continue;
                }
                
                for (int j = 1;j < temp.size();j++) {
                    union_set(temp[0], temp[j]);
                }
            }
        }
        
        int ret = 0;
        for (int i = 0;i <= 100000;i++) {
            if (!hasValue[i]) {
                continue;
            }
            int x = find_set(i);
            if (size[x] > ret) {
                ret = size[x];
            }
        }
        return ret;
    }
};
```

