@代码模板
package Algorithm;
public class UF {
private int[] id;//连通分量的id
private int count;
public UF(int n){
//初始化n个触点
count=n;
id=new int[n];
for (int i = 0; i < n; i++) {
id[i]=i;//初始化时,每个触点都是一个单独的分量
}
}
public int getCount(){
//得到分量数
return count;
}
public boolean connected(int p,int q){
//判断触点p,q是否连通
return find(q)==find(p);
}
public int find(int p){
//找到触点p所在的分量id
}
public void union(int p,int q){
//合并触点p,q
}
}
实现find和union即可。
1.用循环将一个分量中的触点全部改变
public int find(int p){
return id[p];
}
public void union(int p,int q){
int pID=find(p);
int qID=find(q);
if(pID==qID) return;
for (int i = 0; i < id.length; i++) {
if(id[i]==pID) id[i]=qID;
}
count--;
}
2. 链接法
public int find(int p){
while (p!=id[p]) p=id[p];
return p;
}
public void union(int p,int q){
int pID=find(p);
int qID=find(q);
if(pID==qID) return;
id[pID]=qID;
count--;
}
就两个分量,id=[1, 1, 1, 8, 3, 0, 5, 1, 8, 8]。比如下标4的是3,那么说明下标4链接到下标3,在8这个分量里面。
3. 加权树
private int[] sz;//保存树的高度,初始化都为1
public int find(int p){
while (p!=id[p]) p=id[p];
return p;
}
public void union(int p,int q){
int pID=find(p);
int qID=find(q);
if(pID==qID) return;
if(sz[pID]<sz[qID]){
//小树加到大树上面
sz[qID]+=sz[pID];
id[pID]=qID;
}else{
sz[pID]+=sz[qID];
id[qID]=pID;
}
count--;
}
路径压缩
private int find(int p){
if(p==id[p]) return p;
return id[p]=find(id[p]);
}