说是并查集好像很高大上!!!,了解了后其实就是关于数组的奇淫技巧哈哈哈V^V
//并查集YYDS
#include<bits/stdc++.h>
using namespace std;
const int maxn = 10000 + 5;
int pre[maxn], temp[maxn];//并查集的前驱节点数组,临时存变量的数组
int find(int x)//并查集-查:找根节点(压缩路径版:即每个节点的父节点就是根节点)
{
if( x == pre[x])
return x;
return pre[x] = find(pre[x]);//递归找老大
}
void Union(int x,int y)//并查集-并:合并两个节点的根节点
{
int fx = find(x);
int fy = find(y);
//注意本题没有相等的情况
if(fx < fy)//本题可以将最大的数作为根节点
pre[fx] = fy;
if(fy < fx)
pre[fy] = fx;
}
int n, k, q;
set<int>num;//用于存一共有多少个人
int main()
{
for(int i=0; i<maxn; i++)//并查集-初始化前驱数组
{
pre[i] = i;
}
cin>>n;
for(int i=0; i<n; i++)
{
cin>>k;
for(int j=0; j<k; j++)
{
int x;
cin>>x;
//temp[]数组重复赋值即对应临时数组
temp[j] = x;
num.insert(x);//注意其set的插入方法
if(j!=0)
Union(temp[j],temp[j-1]);
}
}
int num1 = 0;
for(int i=1; i<=num.size(); i++)//求部落数
{
if( i == find(i))//就看有多少i就是根节点,那么就有几个部落
num1++;
}
cout<<num.size()<<" "<<num1<<endl;
cin>>q;
for(int i=0; i<q; i++)
{
int x,y;
cin>>x>>y;
if(find(x) == find(y))//原来是这里写错了,写成pre[x] == pre[y],这个肯定是不对的,因为x和y的前驱节点和根节点是不一样的概念
cout<<"Y\n";
else
cout<<"N\n";
}
}