并查集模板:
class UF{
private:
int count;
vector<int> parent;
public:
UF(int n)
{
count=n;
parent.resize(n);
iota(parent.begin(),parent.end(),0);
}
int find(int index)
{
if(index == parent[index])
return index;
parent[index] = find(parent[index]);
return parent[index];
}
void unite(int p,int q)
{
parent[find(p)] = find(q);
}
bool connect(int index1,int index2)
{
return find(index2) == find(index1);
}
};
leetcode990题解:
给你一个数组 equations
,装着若干字符串表示的算式。每个算式 equations[i]
长度都是 4,而且只有这两种情况:a==b
或者 a!=b
,其中 a,b
可以是任意小写字母。你写一个算法,如果 equations
中所有算式都不会互相冲突,返回 true,否则返回 false。
比如说,输入 ["a==b","b!=c","c==a"]
,算法返回 false,因为这三个算式不可能同时正确。
再比如,输入 ["c==c","b==d","x!=z"]
,算法返回 true,因为这三个算式并不会造成逻辑冲突。
我们前文说过,动态连通性其实就是一种等价关系,具有「自反性」「传递性」和「对称性」,其实 ==
关系也是一种等价关系,具有这些性质。所以这个问题用 Union-Find 算法就很自然。
核心思想是,将 equations
中的算式根据 ==
和 !=
分成两部分,先处理 ==
算式,使得他们通过相等关系各自勾结成门派(连通分量);然后处理 !=
算式,检查不等关系是否破坏了相等关系的连通性。
class UF{
private:
int count;
vector<int> parent;
public:
UF(int n)
{
count=n;
parent.resize(n);
iota(parent.begin(),parent.end(),0);
}
int find(int index)
{
if(index == parent[index])
return index;
parent[index] = find(parent[index]);
return parent[index];
}
void unite(int p,int q)
{
parent[find(p)] = find(q);
}
bool connect(int index1,int index2)
{
return find(index2) == find(index1);
}
};
class Solution {
public:
bool equationsPossible(vector<string>& equations) {
UF uf(26);
for(auto str:equations)
{
if(str[1]=='=')
{
int index1=str[0]-'a';
int index2=str[3]-'a';
uf.unite(index1,index2);
}
}
for(auto str:equations)
{
if(str[1]=='!')
{
int index1=str[0]-'a';
int index2=str[3]-'a';
if(uf.connect(index2,index1))
return false;
}
}
return true;
}
};