PTA 部落(並查集)
阿新 • • 發佈:2019-02-10
7-14 部落(35 分)
在一個社群裡,每個人都有自己的小圈子,還可能同時屬於很多不同的朋友圈。我們認為朋友的朋友都算在一個部落裡,於是要請你統計一下,在一個給定社群中,到底有多少個互不相交的部落?並且檢查任意兩個人是否屬於同一個部落。
輸入格式:
輸入在第一行給出一個正整數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 <algorithm> #include <cstring> #include <string> #include <set> using namespace std; #define N 10005 int pre[N],n,k,p[N],m,a,b; void init() { for(int i=0;i<=N;i++) { pre[i]=i; } } int find(int x) { if(pre[x]==x) { return x; }else return pre[x]=find(pre[x]); } int mix(int a,int b) { int fa=find(a); int fb=find(b); if(fa!=fb) { pre[fa]=fb; } } int main() { init(); cin>>n; set<int> se; set<int> see; set<int>::iterator it; while(n--) { memset(p,0,sizeof(p)); cin>>k; for(int i=0;i<k;i++) { cin>>p[i]; se.insert(p[i]); mix(p[0],p[i]); } } for(it=se.begin();it!=se.end();it++) { see.insert(find(*it));//找boss } cout<<se.size()<<" "<<see.size()<<endl; cin>>m; while(m--) { cin>>a>>b; if(find(a)==find(b)) cout<<"Y"<<endl; else cout<<"N"<<endl; } return 0; }