在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。
输入格式:
输入在第一行给出一个正整数N(≤104),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人:
K P[1] P[2] ⋯ P[K]
其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过104。
之后一行给出一个非负整数Q(≤104),是查询次数。随后Q行,每行给出一对被查询的人的编号。
输出格式:
首先在一行中输出这个社区的总人数、以及互不相交的部落的个数。随后对每一次查询,如果他们属于同一个部落,则在一行中输出Y
,否则输出N
。
输入样例:
4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7
输出样例:
10 2
Y
N
代码如下:
#include <iostream>
#include<map>
#include<vector>
using namespace std;
typedef struct node
{
int data;
int rank;
int parent;
}UFSTree;
void MAKE_SET(UFSTree t[], int n)
{
int i;
for (i = 0; i <= n; i++)
{
t[i].data = i;
t[i].rank = 0;
t[i].parent = i;
}
}
int FIND_SET(UFSTree t[], int x)
{
if (x != t[x].parent)
return(FIND_SET(t, t[x].parent));
else
return x;
}
void UNION(UFSTree t[], int x, int y)
{
x = FIND_SET(t, x);
y = FIND_SET(t, y);
if (t[x].rank > t[y].rank)
t[y].parent = x;
else
{
t[x].parent = y;
if (t[x].rank == t[y].rank)
t[y].rank++;
}
}
int main()
{
int M,sum=0;
cin >> M;
UFSTree P[10001];
map<int, int>mp;
vector<int>vp;
MAKE_SET(P, 10000);
for (int i = 0; i < M; i++)
{
int n,M[10001];
cin >> n >> M[0];
if (!mp.count(M[0]))
{
vp.push_back(M[0]);
mp[M[0]] = 1;
sum++;
}
for (int j = 1; j < n; j++)
{
cin >> M[j];
if (!mp.count(M[j]))
{
vp.push_back(M[j]);
mp[M[j]] = 1;
sum++;
}
UNION(P, M[j - 1], M[j]);
}
}
map<int, int>team;
int tsum = 0;
for (int p = 0; p < vp.size(); p++)
{
if (!team.count(FIND_SET(P, vp[p])))
{
team[FIND_SET(P, vp[p])] = 1;
tsum++;
}
}
cout << sum << " " << tsum << endl;
int N;
cin >> N;
for (int k = 1; k <= N; k++)
{
int a, b;
cin >> a >> b;
if (FIND_SET(P, a) == FIND_SET(P, b))
cout << "Y" << endl;
else
cout << "N" << endl;
}
return 0;
}