PAT (Advanced Level) Practice 並查集 相關題ios
father[i]
表示元素 i的父結點father[i] = i
表示元素 i 爲該集合根結點int father[N];
最初每一個元素都是一個獨立的集合算法
for (int i = 0; i <= n; i++) father[i] = i;
對給定結點尋找其根結點:反覆尋找父結點直到根結點數組
int findFather (int x){ while (x != father[x]) x = father[x]; return x; }
int findFather (int x){ if (x == father[x]) return x; else return findFather(father[x]); }
void Union (int a, int b){ int faA = findFather(a); int faB = findFather(b); if (faA != faB) father[faA] = faB; }
將當前結點查詢路徑上全部結點的父節點都指向根節點函數
int findFather (int x){ int y = x; // 將初始查詢結點記錄下來 while (x != father[x]) // 用 x 進行回溯 x = father[x]; // 找到 x 對應根結點記錄在 x 裏 while (y != father[y]){ // 用記錄的初始查詢結點從新回溯 int z = y; //將此結點記錄下來 y = father[y]; //向父結點回溯 father[z] = x; //將當前結點指向根結點 } return x; }
int findFather (int x){ if (x == father[x]) return x; else{ int F = findFather(father[x]); father[x] = F; return F; } }
map<string,string>
存儲父子關係,用 map<string,int>
存儲結點對應參數father.find(name1) == father.end()
),將獨立成一個新集合,將其加入 map 並進行初始化 father[name1] = name1
#include<iostream> #include<map> using namespace std; map<string,string> father; map<string,int> weight, totaltime, membernum, head_num; string findFather(string s){ string t = s; while (father[s] != s) s = father[s]; if (weight[s] < weight[t]){ father[s] = t; father[t] = t; return t; } return s; } void Union(string s1, string s2){ string fa1 = findFather(s1); string fa2 = findFather(s2); if (weight[fa1] > weight[fa2]) father[fa2] = fa1; else father[fa1] = fa2; } int main() { int n, k, time; scanf("%d%d", &n, &k); string name1, name2; for (int i = 0; i < n; i++){ cin >> name1 >> name2 >> time; weight[name1] += time; weight[name2] += time; if (father.find(name1) == father.end()) father[name1] = name1; if (father.find(name2) == father.end()) father[name2] = name2; Union(name1, name2); } for (auto it: father){ totaltime[findFather(it.first)] += weight[it.first]; membernum[findFather(it.first)]++; } for (auto it: membernum) if (it.second > 2 && totaltime[it.first] / 2 > k) head_num[it.first] = it.second; cout << head_num.size() << endl; for (auto it: head_num) cout << it.first << " " << it.second << endl; return 0; }
findFather
函數string findFather(string s){ while (father[s] != s){ string fa = father[s]; if (weight[fa] < weight[s]){ if (father[fa] == fa) father[s] = s; else father[s] = father[fa]; father[fa] = s; } else s = father[s]; } return s; }
注意:合併時,要對此人以前全部人的興趣集合進行檢查,不能檢查到有相同的就停下,有三個點過不去。spa
問題在於若是前面有一我的興趣爲{3},一我的興趣爲{5},如今這我的興趣爲{3,5},在處理這我的以前,前兩我的並不會被放入同一個 cluster 中,只有將如今這我的與前兩我的分別合併,他們三人才能進入同一個 clusterrest
#include<iostream> #include<set> #include<algorithm> #include<vector> #include<unordered_map> using namespace std; int father[1001]; set<int> hobbies[1001]; bool cmp (pair<int,int> a, pair<int,int> b){ return a.second > b.second; } int findFather(int x){ while (x != father[x]) x = father[x]; return x; } void Union(int a, int b){ int faA = findFather(a); int faB = findFather(b); if (faA != faB) father[faA] = faB; } int main() { for (int i = 0; i < 1001; i++) father[i] = i; int n, k, hobby, clusternum = 0; scanf("%d", &n); for (int i = 0; i < n; i++){ scanf("%d: ", &k); for (int j = 0; j < k; j++){ scanf("%d", &hobby); hobbies[i].insert(hobby); } } for (int i = 1; i < n; i++) for (int j = 0; j < i; j++) for (auto it: hobbies[i]) if (hobbies[j].find(it) != hobbies[j].end()) Union(i,j); unordered_map<int,int> peoplenum; for (int i = 0; i < n; i++){ if (father[i] == i) clusternum++; peoplenum[findFather(i)]++; } vector<pair<int,int>> sortnum; for (auto it: peoplenum) sortnum.push_back({it.first,it.second}); sort(sortnum.begin(),sortnum.end(),cmp); printf("%d\n%d",clusternum,sortnum[0].second); for (int i = 1; i < sortnum.size(); i++) printf(" %d",sortnum[i].second); return 0; }
father[i] = i
father[i+1] == i+1
的即爲根節點,根結點樹即爲集合數也即爲樹的棵數#include<iostream> #include<set> using namespace std; int father[10001]; int findFather(int x){ while (x != father[x]) x = father[x]; return x; } void Union(int a, int b){ int faA = findFather(a); int faB = findFather(b); if (faA != faB) father[faA] = faB; } int main() { for (int i = 0; i < 10001; i++) father[i] = i; int n, k, q, q1, q2, fbird, bird, treenum = 0; scanf("%d", &n); set<int> birds; for (int i = 0; i < n; i++){ scanf("%d%d", &k, &fbird); birds.insert(fbird); for (int j = 0; j < k - 1; j++){ scanf("%d", &bird); birds.insert(bird); Union(fbird,bird); } } for (int i = 0; i < birds.size(); i++) if (father[i+1] == i+1) treenum++; printf("%d %d\n", treenum, birds.size()); scanf("%d", &q); for (int i = 0; i < q; i++){ scanf("%d%d", &q1, &q2); printf("%s\n", findFather(q1) == findFather(q2) ? "Yes" : "No"); } return 0; }