7-21 部落(25 分)
阿新 • • 發佈:2019-02-13
7-21 部落(25 分)
在一個社群裡,每個人都有自己的小圈子,還可能同時屬於很多不同的朋友圈。我們認為朋友的朋友都算在一個部落裡,於是要請你統計一下,在一個給定社群中,到底有多少個互不相交的部落?並且檢查任意兩個人是否屬於同一個部落。
輸入格式:
輸入在第一行給出一個正整數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<stdio.h> #include<stdlib.h> #include<iostream> #include<algorithm> #include<string.h> using namespace std; int c[1000001]; int vis[1000002]; //定義標記陣列 int find(int x){ if(c[x]==x) return x; else return c[x]=find(c[x]); } void f(int x,int y){ int a=find(x); int b=find(y); if(a!=b) c[a]=b; } int main(){ int n,m,k,l,q,w,e,r,p; int i,j=0,cnt=0; cin>>n; for(i=1;i<10001;i++){ c[i]=i; } memset(vis,0,sizeof(vis)); for(i=0;i<n;i++){ cin>>p; cin>>q; vis[q]=1;// 標記出現的成員,出現就把該成員記為1 p--; while(p--){ cin>>w; vis[w]=1; f(q,w); } } for(i=0;i<10001;i++) // 在最大範圍內,遍歷該陣列 { if(vis[i]==1){//如果該數字為1的話,證明該數字已經被標記了,那麼就可以記錄個數 cnt++; //這樣就算出了成員的總人數 } } cout<<cnt<<" "; for(i=1;i<=cnt;i++){ //在成員的總人數範圍內 找部落的個數 if(c[i]==i) // 如果是同一個部落裡的人的話,數組裡的數字是和下標不一樣的 如果數組裡面的數字和下標一樣的話 那麼就是一個部落 j++; } cout<<j<<endl; cin>>w; while(w--){ cin>>r>>p; if(find(r)==find(p)) //判斷某兩個成員是否是同一個部落裡的成員,如果經過查詢,它們都能歸結於同一個數字的話,那麼就是同一個部落的成員,否則就不是。 cout<<"Y"<<endl; else cout<<"N"<<endl; } return 0; }