日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

7-25 朋友圈 (25 分)(详解+并查集的了解和应用)

發布時間:2023/12/4 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 7-25 朋友圈 (25 分)(详解+并查集的了解和应用) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一:題目

某學校有N個學生,形成M個俱樂部。每個俱樂部里的學生有著一定相似的興趣愛好,形成一個朋友圈。一個學生可以同時屬于若干個不同的俱樂部。根據“我的朋友的朋友也是我的朋友”這個推論可以得出,如果A和B是朋友,且B和C是朋友,則A和C也是朋友。請編寫程序計算最大朋友圈中有多少人。

輸入格式:
輸入的第一行包含兩個正整數N(≤30000)和M(≤1000),分別代表學校的學生總數和俱樂部的個數。后面的M行每行按以下格式給出1個俱樂部的信息,其中學生從1~N編號:

第i個俱樂部的人數Mi(空格)學生1(空格)學生2 … 學生Mi

輸出格式:
輸出給出一個整數,表示在最大朋友圈中有多少人。

輸入樣例:
7 4
3 1 2 3
2 1 4
3 5 6 7
1 6
輸出樣例:
4

二:思路

利用并查集,求得根節點的得數組,再用map<int,int> 來計算當中重復次數多的個數 也就是根節點相同的個數最大值

三:上碼

#include<bits/stdc++.h> using namespace std;int father[30000]; //int find( int x){ // // while( x != father[x] ) // { // x = father[x]; // } // // return x; //}//壓縮路徑 int find(int x){int r=x;while(father[r]!=r)r=father[r]; //找到他的前導結點int i=x,j;while(i!=r){ //路徑壓縮算法j=father[i]; //記錄x的前導結點father[i]=r; //將i的前導結點設置為r根節點i=j;}return r; } void merge(int x,int y) {int a = find(x);//x的根節點為a int b = find(y);//y的根節點為bif( a != b )father[b] = a;//那么將b的根節點 設為 a }int main() {int N,M;cin >> N >> M;for( int i = 1; i <= N; i++ )father[i] = i; //設置根節點為數組下標,另外元素值為索引 for( int j = 0; j < M; j++ ){int num;cin >> num;vector<int>v;for( int k = 0; k < num; k++ ){int numPeople;cin >> numPeople;v.push_back(numPeople); }for( int i = 0; i < num-1; i++ ){if( find(v[i]) != find(v[i+1]) )merge(v[i],v[i+1]);//比如剛開始的 1和2 他們原來的根節點不同,所以合并 也就是將索引值為2的數組值改為1 即根節點值為1 } }map<int,int>m;for( int i = 1; i <= N; i++){m[find(i)]++; //這里是find(i) 不能是father[i] 否則最后一個測試點答案錯誤} map<int,int>:: iterator t;int max = 0;for(t = m.begin(); t!= m.end(); t++){if( max < t->second )max = t->second;}cout << max;}//7 4 //3 1 2 3 //2 1 4 //3 5 6 7 //1 6// 7 4 // 2 1 4 // 3 5 6 7 // 1 6 // 3 1 2 3

四:并查集的相關知識

這道題用到了并查集,所以我就學了一下并查集,所以把自己的見解也分享給大家(建議 先看視頻 再瀏覽 博客 再自己敲一遍 學習效率高而已,我總是亂著來 以為看幾篇博客就會了,其實最后還是老老實實 去B站看大佬講解視頻 才搞懂)

1:并查集

查集是一種樹型的數據結構,
用于處理一些不相交集合(Disjoint Sets)的合并及查詢問題
1:查詢元素a和元素b是否屬于同一組
2:合并元素a和元素b所在組 (將有相同元素的元素 合并為一個組 )
3:需要初始化一個數組存放父節點,其索引值 代表元素

2:并查集的AC代碼(模板`)

/*并查集是一種樹型的數據結構,用于處理一些不相交集合(Disjoint Sets)的合并及查詢問題1:查詢元素a和元素b是否屬于同一組2:合并元素a和元素b所在組 (將有相同元素的元素 合并為一個組 ) 3:需要初始化一個數組存放父節點,其索引值 代表元素 */#include<bits/stdc++.h> using namespace std;int father[100]; int find( int x){while( x != father[x] ){x = father[x];}return x; } void merge(int x,int y) {int a = find(x);//x的根節點為a int b = find(y);//y的根節點為bif( a != b )father[b] = a;//那么將b的根節點 設為 a }int main() {//初始化: 我們將每一個結點的前導結點設置為自己,//如果在merge函數時未能形成連通,將獨立成點for( int i = 0; i < 10; i++ ){father[i] = i;}}

上方的find函數 效率不高,當處理大數據時,使用并查集查找時,如果查找次數很多,那么使用樸素版的查找方式肯定要超時。比如,有一百萬個元素,每次都從第一百萬個開始找,這樣一次運算就是106,如果程序要求查找個一千萬次,這樣下來就是1013,肯定要出問題的。

所以有了壓縮路徑的算法(就是一棵樹只有葉節點)

void merge(int x,int y){int a=find(x);//x的根節點為aint b=find(y);//y的根節點為bif(a!=b)//如果a,b不是相同的根節點,則說明ab不是連通的pre[a]=b;//我們將ab相連 將a的前導結點設置為b }

如有疑問 請留言! 加油陌生的你

總結

以上是生活随笔為你收集整理的7-25 朋友圈 (25 分)(详解+并查集的了解和应用)的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。