在某聊天软件中,共有n个用户,m个群。如果两个用户A、B之间想要交流的话,只能通过消息链A→user1→user2→…→B进行交流,如果A、B在同一个群里的话,可以直接交流。如果A、B不在同一个群里的话,可以通过若干个中间人进行交流。
现在给出每个用户已经加入的群列表,问这n个用户总共最少还需要再加多少次群,才能使得任意两个用户之间可以进行交流。
输入格式:第一行为两个正整数n和m,表示用户数量和群数量。接下来n行,每行第一个整数为k_i,表示第i个用户所加入的群数量。紧接着k_i个正整数,表示第i个用户加入的群编号(编号从1开始)。
输出格式:输出一个整数,表示这n个用户总共最少还需加群的次数。
#include <bits/stdc++.h>
using namespace std;
int root[100005];
int find(int x){
if(x==root[x])return x;
else return root[x]=find(root[x]);
}
int main(){
int n,m;cin>>n>>m;int t[1000];//表示每个群是否被访问过
for(int i=1;i<=m;i++)t[i]=0;//初始化
int not_all_zero=0,num=0;
for(int i=0;i<n;i++){
int k;cin>>k;//用户加入的群数量
if(k==0){
num++;continue;
}else{
not_all_zero=1;//至少一个用户加群
}
int b;cin>>b;//第一个群编号
if(t[b]==0){
t[b]=1;root[b]=b;//初始化群的父节点
}
for(int i=2;i<=k;i++){
int a;cin>>a;//剩下的k-1个群编号
if(t[a]==0){
t[a]=1;root[a]=a;//初始化父节点
}
root[find(b)]=find(a);//合并两个群
}
}
for(int i=1;i<=m;i++){//如果群i的父节点是自己
if(root[i]==i)num++; //说明它独立
}cout<<num-not_all_zero;
}
输入示例1
2 2
1 2
0
输出示例1
1
解释:用户1加入了群2,用户2未加群。如果他们想要交流的话,有两种方案:第一种是用户1再加入群1,用户2也加入群1,则两个用户总共加群2次;第二种是用户1不再加群,用户2加入群2,则两个用户总共加群1次。因此,最少加群次数为1次。
输入示例2
8 7
0
3 1 2 3
1 1
2 5 4
2 6 7
1 3
2 7 4
1 1
输出示例2
2
第二个样例:用户1加入群2,用户8加入群4。因此,总共最少还需加2次群。
1472

被折叠的 条评论
为什么被折叠?



