1 solutions

  • 2
    @ 2024-5-26 14:48:48

    A1389 亲戚

    经典并查集,无他,唯手熟尔

    题干

    【题目描述】

    若某个家族人员过于庞大,要判断两个是否是亲戚,确实还很不容易,现在给出某个亲戚关系图,求任意给出的某个人所在家族的人数。

    规定:x和y是亲戚,y和z是亲戚,那么x和z也是亲戚。如果x,y是亲戚,那么x的亲戚都是y的亲戚,y的亲戚也都是x的亲戚。

    【输入】

    第一行:三个整数n,(n≤100,000,m≤200,000),分别表示有n个人,m个信息。

    以下m行:信息包含两种形式:

    M a b:表示a和b具有亲戚关系。

    Q a:要求输出a所在家族的人数。

    【输出】

    要求输出a所在家族的人数。

    【输入样例】

    5 10
    M 3 2
    Q 4
    M 1 2
    Q 4
    M 3 2
    Q 1
    M 3 1
    Q 5
    M 4 2
    Q 4
    

    【输出样例】

    1
    1
    3
    1
    4
    

    【来源】

    一本通在线评测

    【样例分析】

    一共5个人,10组关系

    3,2是亲戚 此时1家族:1 2家族:2,3 4家族:4 5家族:5 4家族只有4一个人

    1,2是亲戚 此时1家族:1,2,3 4家族:4 5家族:5 4家族只有4一个人

    3,2是亲戚 已经属于同一集合 1家族有1,2,3三个人

    3,1是亲戚 已经属于同一集合 5家族只有5一个人

    2,4是亲戚 此时1家族:1,2,3,4 5家族:5 4家族有1,2,3,4四个人

    代码+解析:

    #include<bits/stdc++.h>
    using namespace std;
    int n,m,fa[285714],nf[285714];//与A1387一致,我们可以用一个数组统计家族人数
    int Get(int x){
    	return x==fa[x]?x:fa[x]=Get(fa[x]); 
    }
    void Merge(int x,int y){
    	fa[Get(x)]=Get(y);
    }// 并查集基本函数(见A1346)
    int main(){
    	char start;
    	cin>>n>>m;
    	for(int i=1;i<=n;i++){
    		nf[i]=1;
    		fa[i]=i;//初始化
    	}
    	for(int i=1;i<=m;i++){
    		cin>>start;
    		for(int i=0;i<=n;i++){
    			if(Get(i)!=i){
    				nf[Get(i)]+=nf[i];
    				nf[i]=0;//每轮循环开始都归并一次(见A1387)
    			}
    		}
    		if(start=='M'){
    			int a,b;
    			cin>>a>>b;
    			Merge(a,b);// 并集操作
    		}
    		else{
    			int a;
    			cin>>a;
    			cout<<nf[Get(a)]<<endl;// 输出
    		}
    	}
    	return 0;// 自信递交!!!
    }
    

    涉及题目 A1346校外 A1346校内 A1387校外 A1387校内

    点赞,懂?

    • 1

    Information

    ID
    874
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    7
    Tags
    # Submissions
    22
    Accepted
    9
    Uploaded By