1. 程式人生 > >L2-024 部落 (25 分)並查集

L2-024 部落 (25 分)並查集

輸出 pan 輸入格式 void 屬於 find 裏的 sam ott

在一個社區裏,每個人都有自己的小圈子,還可能同時屬於很多不同的朋友圈。我們認為朋友的朋友都算在一個部落裏,於是要請你統計一下,在一個給定社區中,到底有多少個互不相交的部落?並且檢查任意兩個人是否屬於同一個部落。

輸入格式:

輸入在第一行給出一個正整數N(≤),是已知小圈子的個數。隨後N行,每行按下列格式給出一個小圈子裏的人:

K [ [ ? [

其中K是小圈子裏的人數,[(,)是小圈子裏每個人的編號。這裏所有人的編號從1開始連續編號,最大編號不會超過1。

之後一行給出一個非負整數Q(≤),是查詢次數。隨後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 <bits/stdc++.h>
using namespace std;
int n,q;
int par[10004],ran[10004];
int arr[10004];
int find(int a)
{
    if(a==par[a])
        return a;
    else
        return par[a]=find(par[a]);
}
void
unite(int a,int b) { a = find(a); b = find(b); if(a==b) return ; if(ran[a]>ran[b]) par[b] = a; else { par[a] = b; if(ran[a]==ran[b]) ran[b]++; } } bool same(int a,int b) { return find(a) == find(b); }
int main() { cin>>n; for(int i=0;i<10004;i++) { par[i] = i; ran[i] = 0; } int k; set<int> s; while(n--) { cin>>k; for(int i=0;i<k;i++) { cin>>arr[i]; s.insert(arr[i]); } for(int i=1;i<k;i++) unite(arr[i-1],arr[i]); } int sum = s.size(); set<int> ss; for(int i=1;i<=sum;i++) { int t = find(i); ss.insert(t); } cout<<sum<<" "<<ss.size()<<endl; cin>>q; int x,y; while(q--) { cin>>x>>y; if(same(x,y)) cout<<"Y"<<endl; else cout<<"N"<<endl; } return 0; }

 

L2-024 部落 (25 分)並查集