intlargestComponentSize(vector<int>& nums){ int n = nums.size(); int maxComponentSize = INT_MIN;
// DSU* dsu = new DSU(n); // travel all pairs and construct the dsu, o(n ** 2), too slow // for(int i = 0; i < n; ++i) { // for(int j = i; j < n; ++j) { // if(getGreatestCommonDivisor(nums[i], nums[j]) != 1) { // dsu->unionMerge(i, j); // } // } // } // // return *max_element(dsu->subTreeSize.begin(), dsu->subTreeSize.end());
// we shall understand the fact that: // union: union by edeg, but edge denote two set
// find a number's prime factors: map<int, vector<int>> numberToPrimes; for(auto num : nums) { vector<int> primes; int x = num; int d = 2; while(d * d <= num) { if(num % d == 0) { // cull out all d while(num % d == 0) { num = num / d; } primes.emplace_back(d); } ++d; } if(num > 1 || primes.empty()) { primes.emplace_back(num); } numberToPrimes[x] = primes; }
// form all the factors and numbers into nodes unordered_set<int> factors; for(auto& p : numberToPrimes) { for(auto& fac : p.second) { factors.insert(fac); } }
unordered_map<int, int> facToNode; int i = 0; for(auto fac : factors) { facToNode[fac] = i++; }
DSU* dsu = newDSU(factors.size()); // union those numbers by factors for(auto p : numberToPrimes) { vector<int> primes = p.second; // union a number's all factors, we need union action: primes.size() times for(auto prime : primes) { // cout << p.first << "->" << prime << endl; dsu->unionMerge(facToNode[primes[0]], facToNode[prime]); }
}
// for each number, find the union root of this number // all numbers who are connected will share the same root vector<int> cnt(factors.size()); for(auto p : numberToPrimes) { cnt[dsu->find(facToNode[p.second[0]])]++; } return *max_element(cnt.begin(), cnt.end()); // return *max_element(dsu->subTreeSize.begin(), dsu->subTreeSize.end()); // return dsu->maxComponentSize(); } };
boolunionMerge(vector<int>& parent, vector<int>& subTreeSize, int x, int y){ int findX = find(parent, x); int findY = find(parent, y); if(findX != findY) { parent[findX] = findY; subTreeSize[findY] += subTreeSize[findX]; returntrue; } returnfalse; }
intminMalwareSpread(vector<vector<int>>& graph, vector<int>& initial){ int n = graph.size(); vector<int> parent(n); vector<int> subTreeSize(n);
for(int i = 0; i < n; ++i) { parent[i] = i; subTreeSize[i] = 1; } map<int, int> connectSizeToInitial; // cal each connected component's size, attach initial with a component's "color" for(int i = 0; i < n; ++i) { for(int j = 0; j < n; ++j) { if(graph[i][j] == 1) { unionMerge(parent, subTreeSize, i, j); } } }
map<int, int> rootToInit; // if two initial number in same connected component, then remove one of them // will cause the same malware spread result // each color pick a smallest idx as res candidate in initial, finally pick the max connect size // find max connected size int maxConnectSize = INT_MIN; for(auto& i : initial) { int curRoot = find(parent, i); // cout << i << " ->> " << curRoot << endl; if(rootToInit.find(curRoot) != rootToInit.end()) { rootToInit[curRoot] = -1; continue; } rootToInit[curRoot] = i; }
classSolution { public: intfind(vector<int>& parent, int x){ while(x != parent[x]) { parent[x] = parent[parent[x]]; x = parent[x]; }
return x; }
boolunionMerge(vector<int>& parent, int x, int y){ int findX = find(parent, x); int findY = find(parent, y); if(findX != findY) { parent[findX] = findY returntrue; } returnfalse; }
intswimInWater(vector<vector<int>>& grid){ // for each threshold, maintain a unionFind // everytime increase thres, we modify the connection of unionFind int n = grid.size();
if(n == 1) { return0; }
vector<int> parent(n * n); for(int i = 0; i < n * n; ++i) { parent[i] = i; }
// Each value grid[i][j] is unique. vector<vector<int>> elevationToIdx(n * n, vector<int>(n)); for(int i = 0; i < n; ++i) { for(int j = 0; j < n; ++j) { elevationToIdx[grid[i][j]][0] = i; elevationToIdx[grid[i][j]][1] = j; } }
vector<vector<int>> moves = {{0, 1}, {1, 0}, {0, -1}, {-1, 0}}; for(int thres = 0; thres < n * n; ++thres) { // when the rain rise, process the exact the same height grid int tarX = elevationToIdx[thres][0]; int tarY = elevationToIdx[thres][1]; for(auto deltaXY : moves) { int newX = tarX + deltaXY[0]; int newY = tarY + deltaXY[1]; if(newX >= 0 && newY >= 0 && newX < n && newY < n && grid[newX][newY] <= thres) { // cout << newX << " " << newY << " ->" << thres <<endl; unionMerge(parent, grid[newX][newY], grid[tarX][tarY]); if(find(parent, grid[0][0]) == find(parent, grid[n - 1][n - 1])) { return thres; } } } } return n*n; } }