也算是磕磕絆絆,斷斷續續的學歷一段時間並查集了吧,也是時候改寫乙個blog總結一下啦。
先說一下普通並查集吧。
普通並查集就是單純的把某些可以連起來的點用一條有向邊連起來,表示他們屬於「一類」,例如hdu1213,這就是乙個並查集的裸題,直接把輸入的點合併,之後統計有幾個點的祖先是自己就行。
ac**:
#include#includeusing namespace std;
const int maxn=10010;
int f[maxn];
void init(int n)
int find(int x)
void merge(int x,int y)
}int main()
int ans=0;
for(int i=1;i<=n;i++)
printf("%d\n",ans);
}return 0;
}
還有乙個例子就是hdu3635,這個很容易看出是乙個並查集的題,但這個涉及到三個操作,乙個是查詢x的祖先,乙個是查詢x的祖先所在的位置含有的龍珠的個數,還有乙個就是查詢x一共轉移了幾次。第乙個就是乙個基礎的find操作,第二個直接定義乙個sum陣列,在merge的時候把子節點的sum全部給父節點,並將子節點的sum清為0,最後直接查詢就行,主要是最後乙個,我考慮的是並查集維護的是乙個樹(或者說森林),find操作向上查詢了多少次,這顆龍珠就被轉移了多少次,但這樣就必須把路徑壓縮給去掉,所幸資料範圍比較小,就卡過去啦;
ac**:
#include#include#includeusing namespace std;
const int maxn=10010;
int n,m;
int f[maxn],sum[maxn];
int ans;
void init(int n)
}int find(int x)
}void merge(int x,int y)
}int main()
else}}
return 0;
}
當然,一般比賽的時候很少可以看到某個演算法的裸題,有些並查集的題要構建出並查集的模型才行。
例poj1456,看到這題可以想到貪心,但由於資料範圍很小,時限很多,直接暴力做不會超時,但這一題其實是可以用並查集來優化的。我們排序完之後遍歷時最消耗時間就是去查詢從d -> 1哪乙個點還沒有用,那我們就可以考慮並查集,每次將t-1更新為t的父節點,那們每次find操作只要得到的t不為0就可以更新答案。
ac**:
#include#include#includeusing namespace std;
#define ll long long
const int maxn=10010;
struct node
a[maxn];
bool cmp(node aa,node bb)
int f[maxn];
int find(int x)
void init(int n)
}int main()
init(pos);
sort(a+1,a+n+1,cmp);
ll ans=0;
for(int i=1; i<=n; i++)
}printf("%lld\n",ans);
}return 0;
}
而普通並查集在圖論裡的操作還有很多,比如判斷圖是否連通,判斷圖里有沒有環。。。這裡就不一一贅述。
接下來講一下並查集的公升級版,帶權並查集。
就直接更具題目來講吧
poj1182,這是一道帶權並查集的經典題啦。首先我們用0表示x和y是同類,1表示x吃y,2表示x被y吃。那麼根據向量的運算法則,我們就可以把路勁壓縮和merge操作時的表示式給寫出來,這樣這題就可以做出來啦。
ac**:
#include#include#includeusing namespace std;
const int maxn=5e4+7;
int f[maxn],rank[maxn];
void init(int n)
}int find(int x)
}void merge(int x,int y,int val)
}int main()
int t1=find(x),t2=find(y);
int temp;
if(t1==t2)
else
}else
}printf("%d\n",ans);
return 0;
}
帶權並查集還有區間形的,例如這道題hdu3038,我們每次用(x-1,y]來記錄x->y之間的值,還是一樣,直接在路徑壓縮和merge操作時根據向量運算法則寫出表示式就行。
ac**:
#include#includeusing namespace std;
#define ll long long
const ll maxn=200010;
int f[maxn];
ll rank[maxn];
void init(int n)
}int find(int x)
}int main()
else
}else}}
printf("%lld\n",ans);
}return 0;
}
並查集學習筆記
並查集是一種用來管理資料分組狀況的資料結構,可以進行合併操作,但無法進行分割。並查集的結構 並查集也是用樹形結構來實現的,但不是二叉樹。每個資料,元素對應乙個節點,每個組對應一棵樹。並查集的實現 並查集有幾個基本操作初始化 查詢樹的根 合併x,y所屬集合 判斷x,y是否屬於同一集合。查詢是查詢樹的根...
並查集 學習筆記
並查集是由一組互不相交的集合組成的乙個集合結構,並在此集合上定義了運算union和find。即並查集中的元素本身是集合,他們是某個集合的子集,並查集是由這些集合組成的集合結構。並查集上有兩個最基本的運算,find和union。函式find搜尋給定元素i所在的子集合,並返回該自己喝 union運算將兩...
學習筆記 並查集
這是乙個可以實現合併與查詢 元素間關係判定 用來維護多集合 功能多樣化 的超牛批的可以動態維護的樹形結構。這個演算法只要是實現集合元素關係的型別都可以用到,又是線性時間複雜度,而且最關鍵的是它是個高階資料結構,翻譯過來就是這個可以動態維護,所以我覺得這個用途比單純的演算法要好,實際應用比較大,而且這...