【Android開發】SeekBar
阿新 • • 發佈:2021-01-20
並查集
https://www.luogu.com.cn/problem/P3367
並查集問題非常經典,解法非常精妙
首先對每個元素做標號
資料結構就是一個數組,陣列中儲存的是對應根節點的標號
//初始化
for (int i=1;i<=k;i++) {
f[i]=i;
}
所謂並查集,也就只有兩個操作,並和查
首先是查操作
int find(int k) { //如果根節點是自己,那麼返回 if(f[k]==k)return k; //否則找父節點的根節點,並且做一下路徑壓縮,將父節點的根節點置為自己的根節點 return f[k]=find(f[k]); }
然後是並操作
void merge(int a, int b) {
//把a的根節點掛到b的根節點上,如果只把a掛到b上,就無法顧及到a的根節點上的其他節點了
f[find(a)]=find(b);
}
非常巧妙,短短几行程式碼,實現瞭如此複雜而又高效的邏輯
帶權並查集
無權的並查集應用範圍還是比較有限,加上權重,就能實現更復雜的邏輯,例如leetcode 399. 除法求值
帶上權重的話,就需要新增一個數組,儲存權重值,初始化為1
在這道題中,權重是商,那麼 w[i]
含義就是 N[i] = w[i] * N[f[i]]
for (int i=1;i<=k;i++) { f[i]=i; w[i]=1; }
查操作和並操作
int find(int x) { if (f[x]==x) return x; int y=f[x]; int z=find(y); //每進行一次find操作,w陣列也被更新過了,因此用更新過的y再更新x w[x]=w[x]*w[y]; return f[x]=z; } void merge(int a, int b, double k) { int aa=find(a); int bb=find(b); f[aa]=bb; // a/b=k a=w[a]*aa b=w[b]*bb w[aa]=aa/bb 推導可得 w[aa]=k*w[b]/w[a]; }