Cho mảng A các số nguyên dương duy nhất. Xây dựng đồ thị: đỉnh là các phần tử, có cạnh giữa A[i] và A[j] nếu chúng có ước chung > 1. Tìm kích thước thành phần liên thông lớn nhất.
Ví dụ: [4,6,15,35] → 4 (tất cả liên thông qua các ước chung).
Giải thuật
- Dùng Union-Find (DSU) để gom nhóm các số có ước chung.
- Với mỗi số x, phân tích thừa số nguyên tố. Với mỗi ước j (và x/j), union chỉ số hiện tại với chỉ số đầu tiên gặp ước đó (lưu trong map m).
- Cuối cùng, tìm size lớn nhất của các nhóm (rank của root).
Ví dụ mã C++
#include <bits/stdc++.h>
using namespace std;
class Solution {
public:
vector<int> parent, rank;
int getParent(int x){
if (parent[x] == -1) return x;
return parent[x] = getParent(parent[x]);
}
void unionn(int x, int y){
int parX = getParent(x), parY = getParent(y);
if (parX == parY) return;
if (rank[parX] >= rank[parY]) {
rank[parX] += rank[parY];
parent[parY] = parX;
} else {
rank[parY] += rank[parX];
parent[parX] = parY;
}
}
int largestComponentSize(vector<int>& A) {
int ret = 0, n = A.size();
parent = vector<int>(n, -1);
rank = vector<int>(n, 1);
unordered_map<int, int> m;
for (int i = 0; i < n; i++) {
int x = A[i];
for (int j = 2; j * j <= x; j++) {
if (x % j == 0) {
if (m.count(j)) unionn(m[j], i); else m[j] = i;
if (m.count(x/j)) unionn(m[x/j], i); else m[x/j] = i;
}
}
if (m.count(x)) unionn(m[x], i); else m[x] = i;
ret = max(ret, rank[getParent(i)]);
}
return ret;
}
};
int main(){
Solution ob;
vector<int> v = {4,6,15,35};
cout << (ob.largestComponentSize(v));
}
Đầu vào
{4,6,15,35}
Đầu ra
4