基本思想:
主要考察并查集的使用,其中注意节点合并的思想;
关键点:
map排序似乎无法进行,可以转成Vector<pair<string,int>>进行sort排序,条件改写一下就行了;
#include<iostream> #include<stdlib.h> #include<stdio.h> #include<vector> #include<string> #include<math.h> #include<algorithm> #include<cstring> #include<map> #include<queue> using namespace std; const int maxn = 1010; vector<int>father; vector<int>fin; int course[maxn]; int n; void init() { father.resize(n+1); fill(course, course + maxn, 0); for (int i = 0; i < father.size(); i++) { father[i] = i; } } bool cmp(int a, int b) { return a > b; } int findfather(int n) { int temp = n; while (father[n] != n) { n = father[n]; } /* while (father[temp] != n) { int a = father[temp]; father[temp] = n; temp = a; } */ return n; } void contain(int a, int b) { int aa = findfather(a); int bb = findfather(b); if (aa != bb) { father[aa] = bb; } } void cnt() { map<int, int>m; for (int i = 1; i <= n; i++) { int f = findfather(i); m[f]++; } cout << m.size() << endl; bool flag = true; for (auto it = m.begin(); it != m.end();it++) { fin.push_back(it->second); } sort(fin.begin(), fin.end(), cmp); for (int i = 0; i < fin.size(); i++) { if (i == 0) cout << fin[i]; else cout << " " << fin[i]; } } int main() { cin >> n; int a,b; init(); for (int i = 1; i <= n; i++) { scanf("%d: ", &a); //cout << a << endl; for (int j = 0; j < a; j++) { cin >> b; if (course[b] == 0) { //如果第一次访问添加这个课程; course[b] = i; //添加课程内的人; } else { //如果不是的第一次; contain(i, course[b]); //将两个选课相同的人进行合并; } } } //构造完成,进行合并; cnt(); return 0; }