有N我的,若是任意2我的的爱好有相同的(就是有交集),那么这2我的就是属于同一个社交网络,要求输出这N我的组成了几个社交网络,而且输出每一个社交网络的人数算法
此题考察的是并查集的使用(并查集主要用来处理 若干个节点,有些节点互相相连,有些节点没有链接,如何判断其中两个节点是否相连这样的问题),目前来看,使用并查集求解此题应该是最好的选择,能够使用构建人与人的关系图,而后遍历有多少个连通份量,每个连通份量有多少节点,可是这种方式实现起来过于复杂。数组
并查集主要由1个集合,2个操做所组成,集合就是father保存每个节点的父节点,2个操做分别是查询节点x的父亲节点和合并2个节点所在的集合。入下面代码所示:网络
int father[1005];// 每个节点的父亲节点 // 查询节点x的父亲节点 int findFather(int x){ while(x!=father[x]){ x = father[x]; } return x;//father[x]==x的才是根节点 } // 合并a和b节点所在的集合 void Union(int a,int b){ int fa = findFather(a); int fb = findFather(b); if(fa!=fb){ father[fa] = fb; } }
在此题中,咱们须要构建一我的与人之间相互关联的社交网络,媒介是每个人所拥有的爱好,那么咱们使用$hobbyOwner$记录每个爱好的全部者,这样在输入每个爱好的时候,若是当前爱好没有全部者,将当前爱好标记为本身所独有,不然就将该爱好全部者和当前人合并到一个社交网络。在每个社交网络构建完成后,咱们须要统计社交网络的个数和每个社交网络的人数,咱们使用$roots(set集合)$保存每个社交网络的根节点,其个数即为社交网络的个数,$cluster$保存每个社交网络的人数,具体作法就是,须要遍历每个人,找到其根节点$root$,而后添加进$roots$中,而且统计当前社交网络的人数++cluster[root]
。最后对cluster进行排序输出便可。测试
int cluster[1005];// 每个社交网络的人数 unordered_set<int> roots;// 保存每个根节点 // 统计社交网络的个数,也就是根节点的个数 for (int k = 1; k <= N; ++k) { int root = findFather(k); ++cluster[root]; roots.insert(root); }
#include <cstdio> #include <unordered_map> #include <unordered_set> #include <algorithm> using namespace std; int father[1005];// 每个节点的父亲节点 unordered_map<int,int> hobbyOwner;//每个爱好的全部者 int cluster[1005];// 每个社交网络的人数 // 初始化每个节点的父亲 void init(){ for (int i = 1; i <= 1000; ++i) { father[i] = i; } } // 查询节点x的父亲节点 int findFather(int x){ while(x!=father[x]){ x = father[x]; } return x;//father[x]==x的才是根节点 } // 合并a和b节点所在的集合 void Union(int a,int b){ int fa = findFather(a); int fb = findFather(b); if(fa!=fb){ father[fa] = fb; } } bool cmp(int a,int b){ return a>b; } int main() { init(); int N;// 节点个数 scanf("%d",&N); for (int i = 1; i <= N; ++i) { int K; scanf("%d: ",&K); for (int j = 0; j < K; ++j) { int hobby; scanf("%d",&hobby); if(hobbyOwner[hobby]==0){ // 当前爱好没有人拥有 hobbyOwner[hobby] = i; } else { // 已经拥有了,合并拥有者和i Union(hobbyOwner[hobby],i); } } } unordered_set<int> roots;// 保存每个根节点 // 统计社交网络的个数,也就是根节点的个数 for (int k = 1; k <= N; ++k) { int root = findFather(k); ++cluster[root]; roots.insert(root); } printf("%lu\n",roots.size()); sort(cluster+1,cluster+N+1,cmp); for(int i=1;i<=roots.size();++i){ printf("%d",cluster[i]); if(i<roots.size()) printf(" "); } return 0; }