#include <bits/stdc++.h>
using namespace std;
#define MAXN 10005
int visited[MAXN],uset[MAXN],vis[MAXN];
//并查集
int find(int x){
return x == uset[x] ? uset[x] : uset[x] = find(uset[x]) , uset[x];
}
void unit(int x,int y){
x = find(x);
y = find(y);
if(x == y) return;
uset[y] = x;//把后者的根设置为前者
}
int main(){
int n,m;
scanf("%d",&n);
memset(visited,-1,sizeof(visited));//初始化为未访问过,便于统计人数
memset(vis,-1,sizeof(vis));//初始化该集合没有访问过
for(int i=1;i<=MAXN;i++){//n不为人数,总人数未知
uset[i] = i;//根节点初始化为自己
}
int sum = 0,x,father;//总人数
while(n--){
scanf("%d",&m);
for(int i = 0;i < m; i++){
scanf("%d",&x);
if(i == 0) {
father = find(x);//本集合的根节点
}
else if(visited[x] == 1){//已有根节点(树)
//把本集合的根节点粘到已有的根节点集合上,≈合并两个集合
unit(uset[x],father);
}else{//未有根节点(单点),粘这个元素到这个集合上
unit(father,x);
}
if(visited[x] == -1){
visited[x] = 1;//标记已访问
sum++;
}//统计总人数
}
}
//部落数
int cnt = 0;
for(int i = 1;i <= sum;i++){
int tmp = find(i);//根节点
if(vis[tmp]==-1){//未访问过该根节点,记为新的部落数
vis[tmp] = 1;
cnt++;
}
}
printf("%d %d\n",sum,cnt);
int q;
int a,b;
scanf("%d",&q);
for(int i = 0;i < q; i++){
scanf("%d %d",&a,&b);
if(find(a) == find(b)) printf("Y\n");
else printf("N\n");
}
return 0;
}
03-05
371