1. 547. 省份数量
经典题目,找无关联点集的数量
merge并,find查,add添加节点,主要就是三个函数
class unionFind{
public:
unordered_map<int,int> fathers;
int sum=0;
void add(int x){ //添加节点
if(!fathers.count(x)){
fathers[x]=x;
sum++;
}
}
int find(int x){ //找根结点
int root=x;
while(root!=fathers[root]){
root=fathers[root];
}
while(x!=root){
int temp=fathers[x];
fathers[x]=root;
x=temp;
}
return root;
}
bool is_connected(int x,int y){ //判断是否有共同根结点
return find(x) == find(y);
}
void merge(int x,int y){ //合并两个点集
int rootx=find(x);
int rooty=find(y);
if(rootx!=rooty){
fathers[rooty]=rootx;
sum--;
}
}
};
class Solution {
public:
int findCircleNum(vector<vector<int>>& isConnected) {
unionFind uf;
for(int i=0;i<isConnected.size();i++){ 遍历城市
uf.add(i);
for(int j=0;j<i;j++){
if(isConnected[i][j]){
uf.merge(i,j);
}
}
}
return uf.sum;
}
};
2. 959. 由斜杠划分区域
真吉尔爽
把每个小方格划分成了四个区域,每个方格索引为n*i+j
每个小三角之索引为方格索引乘4+j
每个小三角看作一个点,当 / 时,连接1,2和0,3,\ 时连接0,1和2,3,为空格时把连接01,12,23,即四个点都连通
另,每个方格1和它右面方格的3,2和下面方格的0无论如何都是联通的,所以直接连接这几个点(,每次与右、下连接,注意不要越界)
最后连通分量的个数即为答案,所以用并查集做
class Solution {
public:
unordered_map<int,int> father;
int count;
int find(int a){
int root=a;
while(father[root]!=root){
root=father[root];
}
while(a!=root){
int t=father[a];
father[a]=root;
a=t;
}
return root;
}
void merge(int a,int b){
int roota=find(a);
int rootb=find(b);
if(roota!=rootb){
father[roota]=rootb;
count--;
}
}
int regionsBySlashes(vector<string>& grid) {
int n=grid.size();
count=n*n*4;
for(int i=0;i<n*n*4;i++){
father[i]=i;
}
for(int i=0;i<n;i++){
for(int j=0;j<n;j++){
int index=n*i+j;
if(i<n-1){ //与下方合并
int bottom=index+n;
merge(index*4+2,bottom*4);
}
if(j<n-1){ //与右方合并
int right=index+1;
merge(index*4+1,right*4+3);
}
if(grid[i][j]=='\\'){
merge(index*4,index*4+1);
merge(index*4+2,index*4+3);
}
else if(grid[i][j]=='/'){
merge(index*4+1,index*4+2);
merge(index*4,index*4+3);
}
else{
merge(index*4,index*4+1);
merge(index*4+1,index*4+2);
merge(index*4+2,index*4+3);
}
}
}
return count;
}
};
3. 990. 等式方程的可满足性
==具有连通性,先把所有相等的点连通起来,并可记录下互不相等的点
然后遍历互不相等的点,如果本应互不相等的点有连通性(即有式子表明他俩相等)返回false
用c-‘a’表示点的索引,并查集流啤
class Solution {
public:
vector<int> father;
int find(int a){
int root=a;
while(root!=father[root]){
root=father[root];
}
while(a!=root){
int t=father[a];
father[a]=root;
a=t;
}
return root;
}
void merge(int a,int b){
int roota=find(a);
int rootb=find(b);
if(roota!=rootb){
father[roota]=rootb;
}
}
bool equationsPossible(vector<string>& equations) {
father.resize(26);
for(int i=0;i<26;i++){
father[i]=i;
}
vector<pair<int,int>> vec;
for(string str:equations){
int first=str[0]-'a';
int second=str[3]-'a';
if(str[1]=='='){
merge(first,second);
}
else{
vec.push_back(make_pair(first,second));
}
}
for(auto p:vec){
if(find(p.first)==find(p.second)){
return false;
}
}
return true;
}
};