基础:



题目一:



cpp
static constexpr int MAXN = 31;
class Solution {
public:
vector<int> father = vector<int>(MAXN);
int sets;
void build(int m){
for(int i = 0;i<m;i++){
father[i] = i;
}
sets = m;
}
int find(int i){
if(i != father[i]) father[i] = find(father[i]);
return father[i];
}
void combine(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
father[fx] = fy;
sets--;
}
}
int minSwapsCouples(vector<int>& row) {
int n = row.size();
build(n/2);
for(int i = 0;i<n;i+=2){
combine(row[i]/2,row[i+1]/2);
}
return n/2 - sets;
}
};
题目2:



cpp
static constexpr int MAXN = 301;
class Solution {
public:
vector<int> father = vector<int>(MAXN);
int sets;
void build(int n){
for(int i = 0;i<n;i++){
father[i] = i;
}
sets = n;
}
int find(int i){
if(i != father[i]) father[i] = find(father[i]);
return father[i];
}
void combine(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
father[fx] = fy;
sets--;
}
}
int numSimilarGroups(vector<string>& strs) {
int n = strs.size();
int m = strs[0].size();
build(n);
for(int i = 0;i<n;i++){
for(int j = i+1;j<n;j++){
int diff = 0;
for(int k = 0;k<m && diff<3;k++){
if(strs[i][k] != strs[j][k]) diff++;
}
if(diff == 0 || diff == 2) combine(i,j);
}
}
return sets;
}
};
题目3:




cpp
class Solution {
public:
static constexpr int MAXN = 100001;
vector<int> father = vector<int>(MAXN);
int cols;
int sets;
int index(int r,int c){
return r*cols+c;
}
void build(int n,int m,vector<vector<char>>& grid){
cols = m;
sets = 0;
for(int a = 0;a<n;a++){
for(int b = 0,ind;b<m;b++){
if(grid[a][b] == '1'){
ind = index(a,b);
father[ind] = ind;
sets++;
}
}
}
}
int find(int i){
if(i != father[i]) father[i] = find(father[i]);
return father[i];
}
void combine(int a,int b,int c,int d){
int fx = find(index(a,b));
int fy = find(index(c,d));
if(fx != fy){
father[fx] = fy;
sets--;
}
}
int numIslands(vector<vector<char>>& grid) {
int n = grid.size();
int m = grid[0].size();
build(n,m,grid);
for(int i = 0;i<n;i++){
for(int j = 0;j<m;j++){
if(grid[i][j] == '1'){
if(j>0 && grid[i][j-1] == '1') combine(i,j,i,j-1);
if(i>0 && grid[i-1][j] == '1') combine(i,j,i-1,j);
}
}
}
return sets;
}
};
题目4:



cpp
#define MAXN 1001
#define MAXNCOORD 10001
int father[MAXN];
int sets;
void build(int n){
for(int i = 0;i<n;i++){
father[i] = i;
}
sets = n;
}
int find(int i){
if(i != father[i]){
father[i] = find(father[i]);
}
return father[i];
}
void combine(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
father[fx] = fy;
sets--;
}
}
int removeStones(int** stones, int stonesSize, int* stonesColSize) {
int n = stonesSize;
build(n);
int rowFirst[MAXNCOORD];
int colFirst[MAXNCOORD];
memset(rowFirst,-1,sizeof(rowFirst));
memset(colFirst,-1,sizeof(colFirst));
for(int i = 0;i<n;i++){
int row = stones[i][0];
int col = stones[i][1];
if(rowFirst[row] == -1){
rowFirst[row] = i;
}else{
combine(rowFirst[row],i);
}
if(colFirst[col] == -1){
colFirst[col] = i;
}else{
combine(colFirst[col],i);
}
}
return n-sets;
}
题目5:




cpp
class Solution {
public:
static constexpr int MAXN = 100001;
vector<int> father = vector<int>(MAXN);
vector<bool> secret = vector<bool>(MAXN);
void build(int n,int firstPerson){
for(int i = 0;i<n;i++){
father[i] = i;
secret[i] = false;
}
father[firstPerson] = 0;
secret[0] = true;
}
int find(int i){
if(i != father[i]) father[i] = find(father[i]);
return father[i];
}
void combine(int x,int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
father[fx] = fy;
secret[fy] = secret[fy] || secret[fx];
}
}
vector<int> findAllPeople(int n, vector<vector<int>>& meetings, int firstPerson) {
build(n,firstPerson);
sort(meetings.begin(),meetings.end(),[](const vector<int>& a,const vector<int>& b){
return a[2]<b[2];
});
int m = meetings.size();
for(int l = 0,r;l<m;){
r = l;
while(r+1<m && meetings[l][2] == meetings[r+1][2]){
r++;
}
for(int i = l;i<=r;i++){
combine(meetings[i][0],meetings[i][1]);
}
for(int i = l,a,b;i<=r;i++){
a = meetings[i][0];
b = meetings[i][1];
if(!secret[find(a)]){
father[a] = a;
}
if(!secret[find(b)]){
father[b] = b;
}
}
l = r+1;
}
vector<int> ans;
for(int i = 0;i<n;i++){
if(secret[find(i)]) ans.push_back(i);
}
return ans;
}
};
题目6:



cpp
static constexpr int MAXN = 300001;
class Solution {
public:
vector<int> father = vector<int>(MAXN);
vector<int> maxcnt = vector<int>(MAXN);
void build(int n){
for(int i = 0;i<n;i++){
father[i] = i;
maxcnt[i] = 1;
}
}
int find(int i){
if(i != father[i]) father[i] = find(father[i]);
return father[i];
}
int combine(int x,int y,vector<int>& vals){
int fx = find(x);
int fy = find(y);
int path = 0;
if(vals[fx]>vals[fy]){
father[fy] = fx;
}else if(vals[fx]<vals[fy]){
father[fx] = fy;
}else{
path = maxcnt[fx] * maxcnt[fy];
father[fy] = fx;
maxcnt[fx] += maxcnt[fy];
}
return path;
}
int numberOfGoodPaths(vector<int>& vals, vector<vector<int>>& edges) {
int n = vals.size();
build(n);
sort(edges.begin(),edges.end(),[&vals](const vector<int>& a,const vector<int>& b){
return max(vals[a[0]],vals[a[1]]) < max(vals[b[0]],vals[b[1]]);
});
int ans = n;
for(auto & edge : edges){
ans += combine(edge[0],edge[1],vals);
}
return ans;
}
};
题目7:




cpp
static constexpr int MAXN = 301;
class Solution {
public:
vector<bool> virus = vector<bool>(MAXN);
vector<int> infect = vector<int>(MAXN);
vector<int> father = vector<int>(MAXN);
vector<int> size = vector<int>(MAXN);
vector<int> cnts = vector<int>(MAXN);
void build(int n, vector<int>& initial) {
for (int i = 0; i < n; i++) {
virus[i] = false;
cnts[i] = 0;
infect[i] = -1;
father[i] = i;
size[i] = 1;
}
for (int i : initial) {
virus[i] = true;
}
}
int find(int i) {
if (i != father[i]) father[i] = find(father[i]);
return father[i];
}
void combine(int x, int y) {
int fx = find(x);
int fy = find(y);
if (fx != fy) {
father[fx] = fy;
size[fy] += size[fx];
}
}
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
int n = graph.size();
build(n, initial);
// 1. 合并所有未被感染的节点
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (graph[i][j] == 1 && !virus[i] && !virus[j]) {
combine(i, j);
}
}
}
// 2. 标记每个连通块被哪些感染源连接
for (int sick : initial) {
for (int neighbor = 0; neighbor < n; neighbor++) {
if (sick != neighbor && !virus[neighbor] && graph[sick][neighbor] == 1) {
int fn = find(neighbor);
if (infect[fn] == -1) {
infect[fn] = sick;
} else if (infect[fn] != -2 && infect[fn] != sick) {
infect[fn] = -2;
}
}
}
}
// 3. 统计每个感染源能"拯救"的节点数
for (int i = 0; i < n; i++) {
if (i == find(i) && infect[i] >= 0) {
cnts[infect[i]] += size[i]; // 修复3:下标改为 infect[i]
}
}
// 4. 排序并找到最优解
sort(initial.begin(), initial.end());
int ans = initial[0];
int max_cnt = cnts[ans];
for (int i : initial) {
if (cnts[i] > max_cnt) {
ans = i;
max_cnt = cnts[i];
}
}
return ans;
}
};
以上题目和解答来自B站左神(左程云)