資料結構與演算法題目集7-25——朋友圈
阿新 • • 發佈:2018-12-08
我的資料結構與演算法題目集程式碼倉:https://github.com/617076674/Data-structure-and-algorithm-topic-set
原題連結:https://pintia.cn/problem-sets/15/problems/840
題目描述:
知識點:深度優先遍歷、並查集
思路一:深度優先遍歷
用set<int> club[]儲存每個俱樂部對應的學生資訊,用set<int> student[]儲存每個學生對應的俱樂部資訊。
對M個俱樂部進行深度優先遍歷,用bool visited[]陣列標記某俱樂部是否已被訪問過。
遍歷M個俱樂部,如果當前俱樂部未被訪問過,則清空set<int> cluster,代表即將加入一個新的學生編號叢集,深度優先遍歷當前俱樂部編號。
深度優先遍歷函式如下:
在visited陣列中標記當前節點nowVisit已被訪問過,將當前俱樂部的學生加入到cluster中,並遍歷當前俱樂部的所有學生,所有學生又遍歷其對應的所有俱樂部,一旦發現未訪問的俱樂部,即遞迴呼叫函式,深度優先遍歷該俱樂部。
時間複雜度是O(M * N)。空間複雜度是O(30001)。
C++程式碼:
#include<iostream> #include<set> using namespace std; int N, M; set<int> club[1000], student[30001], cluster; bool visited[1000]; int result = 0; void dfs(int nowVisit); int main(){ scanf("%d %d", &N, &M); for(int i = 0; i < M; i++){ int Mi, num; scanf("%d", &Mi); for(int j = 0; j < Mi; j++){ scanf("%d", &num); student[num].insert(i); club[i].insert(num); } } fill(visited, visited + M, false); for(int i = 0; i < M; i++){ if(!visited[i]){ cluster.clear(); dfs(i); if(cluster.size() > result){ result = cluster.size(); } } } printf("%d\n", result); return 0; } void dfs(int nowVisit){ visited[nowVisit] = true; for(set<int>::iterator it = club[nowVisit].begin(); it != club[nowVisit].end(); it++){ cluster.insert(*it); } for(set<int>::iterator it1 = club[nowVisit].begin(); it1 != club[nowVisit].end(); it1++){ for(set<int>::iterator it2 = student[*it1].begin(); it2 != student[*it1].end(); it2++){ if(!visited[*it2]){ dfs(*it2); } } } }
C++解題報告:
思路二:並查集
每個俱樂部的學生擁有相同的父親節點。
時間複雜度和空間複雜度均是O(N)。
C++程式碼:
#include<iostream> #include<set> using namespace std; int N, M, father[30001]; int findFather(int x); void unionTwo(int a, int b); int main(){ scanf("%d %d", &N, &M); for(int i = 1; i <= N; i++){ //並查集的初始化 father[i] = i; } for(int i = 0; i < M; i++){ int Mi; scanf("%d", &Mi); int students[Mi]; for(int j = 0; j < Mi; j++){ scanf("%d", &students[j]); } for(int j = 1; j < Mi; j++){ unionTwo(students[j - 1], students[j]); } } int count[N + 1]; fill(count + 1, count + N + 1, 0); for(int i = 1; i <= N; i++){ count[findFather(i)]++; } int result = 0; for(int i = 1; i <= N; i++){ if(count[i] > result){ result = count[i]; } } printf("%d\n", result); return 0; } int findFather(int x){ int a = x; while(x != father[x]){ x = father[x]; } while(a != father[a]){ int z = a; a = father[a]; father[z] = x; } return x; } void unionTwo(int a, int b){ int a_father = findFather(a); int b_father = findFather(b); if(a_father != b_father){ father[a_father] = b_father; } }
C++解題報告: