假如已知有n個人和m對好友關係(存於數字r)。如果兩個人是直接或間接的好友(好友的好友的好友...),則認為他們屬於同乙個朋友圈,請寫出程式求出這n個人裡一共有多少朋友圈。
例如:n=5,m=3,r=,,},表示有5個人,1和2是好友,2和3是好友,4和5是好友。則1,2,3屬於乙個朋友圈,4,5屬於另乙個朋友圈,結果為兩個朋友圈。
這道題有很多種解法,首先想到的就是定義乙個陣列,陣列元素也是陣列。使用stl庫,定義這樣的乙個結構:
vector> _v;
然後遍歷每對好友關係,如果陣列中有相同元素(好友),就在當前陣列中新增該好友,最後,遍歷最外層陣列元素個數就可以知道有多少個朋友圈了。
作為小公尺麵試題,它不僅要求正確性還有效率,上面給出的解法也能做出這道題,但是效率太低,所以,在這裡,我使用一種更高效,快捷的資料結構-----並查集。
並查集:
並查集是一種樹型的
資料結構
,用於處理一些不相交
集合(disjoint sets)的合併及查詢問題。常常在使用中以
森林來表示。集就是讓每個元素構成乙個單元素的集合,也就是按一定順序將屬於同一組的元素所在的集合合併。在一些有n個元素的集合應用問題中,通常是在開始時讓每個元素構成乙個單元素的集合,然後按一定順序將屬於同一組的元素所在的集合合併,其間要反覆查詢乙個元素在哪個集合中。
如圖所示:
查詢根:
int getroot(int root)
return root;
}
合併朋友圈(判斷x1與x2是否已經為好友關係,不是則並合併到所在朋友圈):
void union(int x1,int x2)
}
int count()
return count-1;//因為0號位置不用,但初始化時初始化為了-1,需要減去多算的這乙個
}
整體**:
#pragma once
#include using namespace std;
#include #include class unionset
return root;
} void union(int x1,int x2) }
bool find(int x1,int x2)
int count()
return count-1; }
protected:
//vectorv;
int* _unionset;
int _n;
};int friend(int n,int m,int r[2])
,,,};//n=總人數,m=多少對好友關係
cout<
並查集(小公尺麵試題求朋友圈的個數)
一 並查集的引入 以小公尺的這道題為例 並查集定義 並查集實際上是右乙個陣列實現的,這個陣列比較特殊,最開始將陣列的每乙個資料看成乙個單獨的集合,用 1表示。然後根據題目要求1和2可以合併,將第2個資料合併到1上時,array 1 array 2 array 2 1 陣列的array 1 儲存其與a...
PAT 朋友圈(並查集)
某學校有n個學生,形成m個俱樂部。每個俱樂部裡的學生有著一定相似的興趣愛好,形成乙個朋友圈。乙個學生可以同時屬於若干個不同的俱樂部。根據 我的朋友的朋友也是我的朋友 這個推論可以得出,如果a和b是朋友,且b和c是朋友,則a和c也是朋友。請編寫程式計算最大朋友圈中有多少人。輸入的第一行包含兩個正整數n...
5 9 朋友圈 (並查集)
某學校有n個學生,形成m個俱樂部。每個俱樂部裡的學生有著一定相似的興趣愛好,形成乙個朋友圈。乙個學生可以同時屬於若干個不同的俱樂部。根據 我的朋友的朋友也是我的朋友 這個推論可以得出,如果a和b是朋友,且b和c是朋友,則a和c也是朋友。請編寫程式計算最大朋友圈中有多少人。輸入的第一行包含兩個正整數n...