朋友圈(集合的等价关系)
[问题描述]
某学校有N个学生,形成M个俱乐部。每个俱乐部里的学生有着相似的兴趣爱好,形成一个朋友圈。一个学生可以同时属于若干个不同的俱乐部。根据“我的朋友的朋友也是我的朋友”这个推论可以得出,如果A和B是朋友,且B和C是朋友,则A和C也是朋友。请编写程序计算最大朋友圈中有多少人。
[基本要求]
(1)输入说明:输入的第一行包含两个正整数N (N<=30 000)和M (M<=1000),分别代表学校的学生总数和俱乐部的个数。随后的M行每行按以下格式给出一个俱乐部的信息,其中学生从1-N编号:
第i个俱乐部的人数Mi(空格)学生1(空格)学生2… 学生Mi
(2)输出说明:输出一个整数,表示在最大朋友圈中有多少人。
(3)测试用例:
输入 7 4
3 1 2 3
2 1 4
3 5 6 7
1 6
输出 4
数据结构
两个数组
int student[N+1];//存储学生数量
int frinds[M+1];//存储朋友圈
算法思想:
1.设置学生数组,数组编号表示学生编号,
(1)初始值均为-1,表示这个学生没有朋友圈,
(2)若学生数组的值为正数x,表示这个学生有所属的朋友圈,且这个朋友圈的中心学生编号为x;
(3)若学生数组的值x小于负一,则表示这个学生是某个朋友圈的中心学生,且这个朋友圈的总人数为x的绝对值;
2.再设置朋友圈数组,依次存储这个俱乐部内的学生编号。
3.假定每个俱乐部的第一位同学为这个朋友圈的中心,那么将他在学生数组里的值置为当前俱乐部的学生人数的负数,这个俱乐部其他学生在学生数组里的值置为这个朋友圈的中心学生的编号,表示他们共有一个朋友圈。
4.设置函数,从文件中一次读取一个俱乐部信息,存到朋友圈数组中,并传给此函数,设置循环遍历朋友圈数组,按步骤一执行操作;
5.得到最终学生数组,数组中有几个负数便表示有几个朋友圈,最小负数的绝对值即为最大朋友圈的人数;
测试数据和结果
算法时间复杂度
void find_leader( int student[], int N, int frinds[], int num )
时间复杂度:O(n)
代码如下:
#include <iostream>
#include<stdio.h>
#include<math.h>
using namespace std;
void find_leader( int student[], int N, int frinds[], int num )
{
int i, j, k;
j = frinds[0]; //假定每个盆友圈的第一个人是中心
for ( i=1; i<num; i++ )
{
//j号学生有盆友圈,中心为j号学生所附上的编码
if ( student[j]>-1 )
j = student[j];
k = frinds[i]; //k为学生的编号
if ( j!=student[k] )
{
if ( student[k]==-1 ) //k号学生没有盆友圈
{
student[j] += student[k]; //累计第一个的人在这个俱乐部的朋友数
student[k] = j;//中心仍为j
}
else if ( student[k]<-1 ) //k号学生有盆友圈,且为中心
{
student[j] = k; //j号学生附上k的编码
student[k]--;
j = k; //将中心更为k号学生
}
//k号学生有盆友圈,中心为k号学生所附上的编码
else if ( student[k]>-1 )
{
student[j] = student[k];
j = student[k];
}
}
}
}
//输出结果
void show ( int student[], int N )
{
int i, big, num=0;
big = student[1];
for ( i=2; i<=N; i++ )
{
if ( student[i]<big ) //因为是负数,所以用小于
big = student[i];
}
for ( i=1; i<=N; i++ )
if ( student[i]<0 )
num++;
cout<<"共有"<<num<<"个朋友圈"<<endl;
cout<<"最大朋友圈人数:"<< -big;
}
int main()
{
int N, M, i, j, num;
cin >> N >> M;
int student[N+1];
for ( i = 0; i<=N; i++ )
student[i] = -1;
for ( i = 1; i<=M; i++ )
{
cin >> num; //此盆友圈的人数
int frinds[num];
for ( j = 0; j<num; j++ )
cin >> frinds[j]; //存储朋友圈里的学生
find_leader ( student, N, frinds, num ) ;
}
show ( student, N );
return 0;
}