一.問題
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); } }