一.問題
1.問題描述:
有n個點(1...n),輸入整數對(8,9),表示8,9點之間存在相互的連接關系。
動態連通性問題--編寫一段程序過濾掉所以無意義的整數對,即為在不破壞圖連通性的前提下,以最簡單的方式表示圖的連通性。2.實現方案:設計數據結構保存已經存在的整數對,並且用他們來判斷新數對是否滿足新相連關系。
3.實例應用:網絡連接問題,電子觸電設計,社交網絡關系等等
二.解決
1.定義問題--設計api
| public class UF//(類名大寫) | ||
| (構造方法) | UN(int N) | 初始化0-N個觸點 |
| void | union(int p,int q) | 在兩點之間建立連接 |
| int | find(int p) | 在觸點集中找到p |
| boolean | connected(int p,int q) | 判斷觸點p,q是否相連 |
| int | count() | 連通分量的計數 |
2.方案設計
<一>兩個變量
count--用於連通分量的計數&&id[]--數組下標表示連通分量
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
初始化時下標默認為自身下標
在輸入連通關系后(3,4),(5,6)
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
| 0 | 1 | 2 | 4 | 4 | 6 | 6 | 7 | 8 | 9 |
將所以id[3]相同的下標修改為id[4]
從而表示數組的相連關系
1.quick-find
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;//直接return用於方法的推出
for(int i=0;i<id.length;i++)
if(id[i]==pid)id[i]=qid;
count--;
}
每次union需要訪問數組(N+3)到(2N+1)次
2.quick-union
private int find(int p){
while(p!=id[p]){//找出根結點
p=id[p];
}
return p;
}
private void union(int p,int q){
int prot=find(p);
int qrot=find(q);
if(qrot==prot)return;
id[qrot]=prot;
count--;
}
3.union-find算法,加權
public class UF {
private int[] id;
private int[] sz;
private int count;
//初始化
public UF(int N){
count=N;
id=new int[N];
sz=new int[N];
for(int i=0;i<N;i++){
id[i]=i;
sz[i]=1;
}
}
private int find(int p){
while(p!=id[p]){//找出根結點
p=id[p];
}
return p;
}
private void union(int p,int q){
int i=find(p);
int j=find(q);
if(i==j)return;
if(sz[i]<sz[j]){
id[i]=j;sz[j]+=sz[i];
}else{
id[j]=i;sz[i]+=sz[j];
}
count--;
}
//對聯通分量進行計數
public int count(){return count;}
//判斷是否連接
public boolean connected(int p,int q){
return find(p)==find(q);
}
}
