並查集(Disjoint Set)
阿新 • • 發佈:2022-04-07
解決的問題
查詢圖是否成環
理解過程
思想
右邊圖代表著圈裡面的點是連通的
成環的標誌是:圈內某兩元素之間還有一條邊
轉化為程式碼(合併兩個圈)
利用陣列建樹,陣列元素值代表該位置的父親結點,-1代表為獨立結點
因此:
合併兩圈=把a2圖的頭結點的父親結點改為a1圖的頭結點
當發現某條邊的兩個結點的根節點是同一結點時,代表著成環了
可能會出先這種情況,複雜度變為O(n)
因此需要演算法優化:壓縮路徑
用root記錄樹的高度,
if (root[x]> root[y])
則 :y樹拼到x樹
且新root=root[x];
程式碼
#include <bits/stdc++.h> using namespace std; int pre[30005]; int root[35500]; int find(int x) { if (pre[x] != x) { pre[x] = find(pre[x]); } return pre[x]; } void join(int x, int y) { int fx = find(x); int fy = find(y); if (fx != fy) { pre[fx] = fy; } } int main() { int n,m; cin>>n>>m; for(int i=1;i<=n;i++) { pre[i]=i; } while(m--) { int k; cin>>k; int arr[30000]; for(int i=1;i<=k;i++) { cin>>arr[i]; } for(int i=2;i<=k;i++) { join(arr[i],arr[i-1]); } } int ans=0; for(int i=1;i<=n;i++) { int t=find(i); root[t]++; ans=max(root[t],ans); } cout<<ans<<endl; return 0; }