051.并查集
模板0
class UF{
private:
vector<int>fa;
public:
UF(int n):fa(n){
for(int i=0;i<n;++i){
fa[i]=i;
}
}
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
bool check(int a,int b){
return find(a)==find(b);
}
int merge(int a,int b){
int A=find(a);
int B=find(b);
if(A==B)return 0;//已连通返回0
fa[A]=B;
return 1;//连通成功返回1
}
};
模板1
class UF{
private:
int cnt;//连通分量数量
vector<int>fa;
public:
UF(int n):cnt(n),fa(n){
for(int i=0;i<n;++i){
fa[i]=i;
}
}
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
bool check(int a,int b){
return find(a)==find(b);
}
int merge(int a,int b){
int A=find(a);
int B=find(b);
if(A==B)return 0;//已连通返回0
fa[A]=B;
cnt--;
return 1;//连通成功返回1
}
int count(){
return cnt;
}
};
模板2 小挂大
class UF{
private:
int cnt;
vector<int>siz;
vector<int>fa;
public:
UF(int n):cnt(n),fa(n),siz(n){
for(int i=0;i<n;++i){
fa[i]=i;
siz[i]=1;
}
}
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
bool check(int a,int b){
return find(a)==find(b);
}
int merge(int a,int b){
int A=find(a);
int B=find(b);
if(A==B)return 0;
if(siz[A]>siz[B]){
fa[B]=A;
siz[A]+=siz[B];
}
else{
fa[A]=B;
siz[B]+=siz[A];
}
cnt--;
return 1;
}
int count(){
return cnt;
}
};
静态
const int N=1e5+5;
int fa[N];
int siz[N];
int cnt;
void built(int n){
cnt=n;
for(int i=0;i<n;++i){
fa[i]=i;
siz[i]=1;
}
}
int find(int x){
if(fa[x]!=x){
fa[x]=find(fa[x]);
}
return fa[x];
}
bool check(int a,int b){
return find(a)==find(b);
}
int merge(int a,int b){
int A=find(a);
int B=find(b);
if(A==B)return 0;
if(siz[A]>siz[B]){
fa[B]=A;
siz[A]+=siz[B];
}
else{
fa[A]=B;
siz[B]+=siz[A];
}
cnt--;
return 1;
}
习题
差分约束
class Solution {
vector<int>fa;
void built(int n){
fa.resize(n);
for(int i=0;i<n;++i){
fa[i]=i;
}
}
int find(int x){
if(fa[x]!=x){
fa[x]=find(fa[x]);
}
return fa[x];
}
bool check(int a,int b){
return find(a)==find(b);
}
void merge(int a,int b){
int A=find(a);
int B=find(b);
fa[A]=B;
}
public:
bool equationsPossible(vector<string>& equations) {
built(26);
for(auto x:equations){
if(x[1]=='='){
merge(x[0]-'a',x[3]-'a');
}
}
for(auto x:equations){
if(x[1]=='!'){
if(check(x[0]-'a',x[3]-'a')){
return 0;
}
}
}
return 1;
}
};
情侣牵手
class Solution {
class UF{
vector<int>fa;
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
public:
UF(int n):fa(n){
for(int i=0;i<n;++i)fa[i]=i;
}
void merge(int a,int b){
fa[find(a)]=find(b);
}
bool check(int a,int b){
return find(a)==find(b);
}
};
public:
int minSwapsCouples(vector<int>& row) {
int n=row.size();
int cnt=n/2;
UF st(cnt);
for(int i=0;i+1<n;i+=2){
int a=row[i]>>1;
int b=row[i+1]>>1;
if(!st.check(a,b)){
st.merge(a,b);
cnt--;
}
}
return n/2-cnt;
}
};
相似字符串
class Solution {
class UF{
vector<int>fa;
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
public:
UF(int n):fa(n){
for(int i=0;i<n;++i)fa[i]=i;
}
void merge(int a,int b){
fa[find(a)]=find(b);
}
bool check(int a,int b){
return find(a)==find(b);
}
};
public:
int numSimilarGroups(vector<string>& strs) {
int n=strs.size();
int m=strs[0].size();
int cnt=n;
UF st(n);
for(int i=0;i+1<n;++i){
for(int j=i+1;j<n;++j){
if(!st.check(i,j)){
int diff=0;
for(int k=0;k<m;++k){
if(strs[i][k]!=strs[j][k]){
diff++;
}
}
if(diff==0||diff==2){
st.merge(i,j);
cnt--;
}
}
}
}
return cnt;
}
};
移除石头
class Solution {
class UF{
vector<int>fa;
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
public:
UF(int n):fa(n){
for(int i=0;i<n;++i)fa[i]=i;
}
int merge(int a,int b){
if(check(a,b))return 0;
fa[find(a)]=find(b);
return 1;
}
bool check(int a,int b){
return find(a)==find(b);
}
};
public:
int removeStones(vector<vector<int>>& stones) {
int n=stones.size();
UF st(n);
int cnt=0;
unordered_map<int,int>row;
unordered_map<int,int>col;
for(int i=0;i<n;++i){
int x=stones[i][0];
int y=stones[i][1];
if(row.count(x)==0){
row[x]=i;
}
else cnt+=st.merge(row[x],i);
if(col.count(y)==0){
col[y]=i;
}
else cnt+=st.merge(col[y],i);
}
return cnt;
}
};
知道秘密的专家
class Solution {
vector<int>fa;
vector<int>vis;
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
void merge(int a,int b){
int A=find(a);
int B=find(b);
fa[A]=B;
if(vis[A]||vis[B]){
vis[A]=vis[B]=1;
}
}
public:
vector<int> findAllPeople(int n, vector<vector<int>>& met, int fir) {
sort(met.begin(),met.end(),[&](auto &a,auto &b){return a[2]<b[2];});
fa.resize(n);
vis.resize(n);
for(int i=0;i<n;++i){
fa[i]=i;
vis[i]=0;
}
vis[0]=vis[fir]=1;
fa[fir]=0;
int m=met.size();
for(int l=0;l<m;){
int r=l;
while(r+1<m&&met[l][2]==met[r+1][2])r++;
for(int i=l;i<=r;++i){
int x=met[i][0];
int y=met[i][1];
merge(x,y);
}
for(int i=l;i<=r;++i){
int x=met[i][0];
int y=met[i][1];
if(vis[find(x)]==0){
fa[x]=x;
}
if(vis[find(y)]==0){
fa[y]=y;
}
}
l=r+1;
}
vector<int>ans;
for(int i=0;i<n;++i){
if(vis[find(i)])ans.push_back(i);
}
return ans;
}
};
好路径数目
class Solution {
vector<int>fa;
vector<int>cnt;
void built(int n){
fa.resize(n);
cnt.resize(n);
for(int i=0;i<n;++i){
cnt[i]=1;
fa[i]=i;
}
}
int find(int x){
if(fa[x]!=x){
fa[x]=find(fa[x]);
}
return fa[x];
}
int merge(int a,int b,vector<int>&v){
int A=find(a);
int B=find(b);
int path=0;
if(v[A]>v[B]){
fa[B]=A;
}
else if(v[A]<v[B]){
fa[A]=B;
}
else{
path=cnt[A]*cnt[B];
fa[A]=B;
cnt[B]+=cnt[A];
}
return path;
}
public:
int numberOfGoodPaths(vector<int>& v, vector<vector<int>>& e) {
int n=v.size();
built(n);
sort(e.begin(),e.end(),[&](auto &a,auto &b){
return max(v[a[0]],v[a[1]])<max(v[b[0]],v[b[1]]);
});
long ans=n;
for(auto x:e){
ans+=merge(x[0],x[1],v);
}
return ans;
}
};
病毒转播
class Solution {
vector<int>fa;
vector<int>siz;
vector<bool>isinit;
vector<int>init;
vector<int>cnt;
void built(int n){
fa.resize(n);
siz.resize(n);
isinit.resize(n);
init.resize(n);
cnt.resize(n);
for(int i=0;i<n;++i){
cnt[i]=0;
fa[i]=i;
siz[i]=1;
isinit[i]=0;
init[i]=-1;
}
}
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
void merge(int a,int b){
int A=find(a);
int B=find(b);
if(A==B)return;
fa[A]=B;
siz[B]+=siz[A];
}
public:
int minMalwareSpread(vector<vector<int>>& graph, vector<int>& initial) {
int n=graph.size();
built(n);
for(int x:initial){
isinit[x]=1;
}
for(int i=0;i+1<n;++i){
for(int j=i+1;j<n;++j){
if(!isinit[i]&&!isinit[j]&&graph[i][j]==1){
merge(i,j);
}
}
}
for(int x:initial){
for(int i=0;i<n;++i){
if(graph[x][i]&&!isinit[i]){
int f=find(i);
if(init[f]==-1){
init[f]=x;
}
else{
if(init[f]!=x)init[f]=-2;
}
}
}
}
for(int i=0;i<n;++i){
if(find(i)==i&&init[i]!=-1&&init[i]!=-2){
cnt[init[i]]+=siz[i];
}
}
int ans=initial[0];
for(int x:initial){
if(cnt[x]>cnt[ans]){
ans=x;
}
if(cnt[x]==cnt[ans]){
ans=min(ans,x);
}
}
return ans;
}
};
限制边长的路径
class Solution {
vector<int>fa;
void built(int n){
fa.resize(n);
for(int i=0;i<n;++i){
fa[i]=i;
}
}
int find(int x){
if(x!=fa[x]){
fa[x]=find(fa[x]);
}
return fa[x];
}
bool check(int a,int b){
return find(a)==find(b);
}
bool merge(int a,int b){
int A=find(a);
int B=find(b);
if(A==B)return 0;
fa[A]=B;
return 1;
}
public:
vector<bool> distanceLimitedPathsExist(int n, vector<vector<int>>& e, vector<vector<int>>& Q) {
built(n);
int m=e.size();
int q=Q.size();
for(int i=0;i<q;++i){
Q[i].push_back(i);
}
sort(Q.begin(),Q.end(),[&](auto a,auto b){return a[2]<b[2];});
sort(e.begin(),e.end(),[&](auto a,auto b){return a[2]<b[2];});
int i=0;
vector<bool>ans(q);
for(auto x:Q){
int id=x[3];
int u=x[0],v=x[1],k=x[2];
while(i<m&&e[i][2]<k){
merge(e[i][0],e[i][1]);
++i;
}
ans[id]=(check(u,v));
}
return ans;
}
};
I am the bone of my sword

浙公网安备 33010602011771号