部落(pta)(并查集) Java以及C++

简介: 部落(pta)(并查集) Java以及C++

题目描述:

在一个社区里,每个人都有自己的小圈子,还可能同时属于很多不同的朋友圈。我们认为朋友的朋友都算在一个部落里,于是要请你统计一下,在一个给定社区中,到底有多少个互不相交的部落?并且检查任意两个人是否属于同一个部落。

输入格式:

输入在第一行给出一个正整数N(≤10

4

),是已知小圈子的个数。随后N行,每行按下列格式给出一个小圈子里的人:

K P[1] P[2] ⋯ P[K]

其中K是小圈子里的人数,P[i](i=1,⋯,K)是小圈子里每个人的编号。这里所有人的编号从1开始连续编号,最大编号不会超过10

4

之后一行给出一个非负整数Q(≤10

4

),是查询次数。随后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

解题思路:

利用并查集,用set集合存放数据

代码:

java(超时)

package text2;

import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;

public class 部落 {
  static int p[] = new int[10005];
  public static void main(String[] args) {
    // TODO Auto-generated method stub
    for(int i=0;i<10005;i++)
      p[i] = i;
    Set<Integer> numberS = new HashSet<Integer>();
    Set<Integer> numberP = new HashSet<Integer>();
    Scanner scanner = new Scanner(System.in);
    int n = scanner.nextInt();
    for(int i=0;i<n;i++) {
      int p = scanner.nextInt();
      int f = scanner.nextInt();
      numberS.add(f);
      for(int j=1;j<p;j++) {
        int t = scanner.nextInt();
        numberS.add(t);//加入总人数的集合
        Union(f, t);//合并
      }
    }
    System.out.print(numberS.size()+" ");
    for(Integer s:numberS) {
      numberP.add(Find(s));
    }
    System.out.println(numberP.size());
    int m = scanner.nextInt();
    for(int i=0;i<m;i++) {
      int a = scanner.nextInt();
      int b = scanner.nextInt();
      if(Find(a)==Find(b))
        System.out.println("Y");
          else
            System.out.println("N");  
    }
  }
  //找祖先
  public static int Find(int a) {
    if(p[a]!=a) {
      return Find(p[a]);
    }
    return p[a];
  }
//合并两个点的祖先
  public static void Union(int a,int b) {
    a = Find(a);
    b = Find(b);
    if(a!=b) {
      p[a]=b;
    }
  }
}

C++(AC):

#include<iostream>
#include<algorithm>
#include<stack>
#include<set>
#define inf 0x3f3f3f3f
using namespace std;
int par[10005];

void init(){
    for(int i=0;i<10000;i++){
        par[i]=i;
    }
}

int findEle(int a){        //找到祖先
    if(a!=par[a]){
        return par[a]=findEle(par[a]);
    }
    return par[a];
}

void unionEle(int a,int b){   //合并两个点
    a=findEle(a);
    b=findEle(b);
    if(a!=b)
        par[a]=b;
}
int main()
{
    int n,q;
    cin>>n;
    init();
    set<int>st;
    set<int>stt;
    for(int i=0;i<n ;i++){
        int k;
        cin>>k;
        int a[10005];
        cin>>a[0];
        st.insert(a[0]);
        for(int j=1;j<k;j++){
            cin>>a[j];
            st.insert(a[j]);
            unionEle(a[0],a[j]);
        }
    }
    cout<<st.size()<<" ";
    for(auto it=st.begin();it!=st.end();it++){
        stt.insert(findEle(*it));
    }
    cout<<stt.size()<<endl;
    cin>>q;
    for(int i=0;i<q;i++){
        int a,b;
        cin>>a>>b;
        if(findEle(a)==findEle(b))
            cout<<"Y"<<endl;
        else
            cout<<"N"<<endl;   
    }
    system("pause");
    return 0;
}

相关文章
|
20天前
|
存储 C++
【PTA】L1-039 古风排版(C++)
【PTA】L1-039 古风排版(C++)
10 1
|
20天前
|
Java API C++
Java JNI开发时常用数据类型与C++中数据类型转换
Java JNI开发时常用数据类型与C++中数据类型转换
31 0
|
12天前
|
Java Go C#
编程语言C#、C++、Java、Python、go 选择哪个好?
我想说的是,不论选择哪种编程语言,决定选择的都是你最终的目的,做选择之前,先充分调研每一个选择项,再做选择思路就会非常清晰了。
30 3
|
13天前
|
Java C++
java和C++的标志符可以是中文(虽然不提倡)
java和C++的标志符可以是中文(虽然不提倡)
|
20天前
|
存储 人工智能 C++
【PTA】L1-064 估值一亿的AI核心代码(详C++)
【PTA】L1-064 估值一亿的AI核心代码(详C++)
15 1
|
20天前
|
存储 C++ 索引
【PTA】L1-059 敲笨钟(C++)
【PTA】L1-059 敲笨钟(C++)
11 1
|
20天前
|
存储 人工智能 C++
【PTA】L1-093 猜帽子游戏(C++)
【PTA】L1-093 猜帽子游戏(C++)
18 1
|
20天前
|
C++
【PTA】L1-046 整除光棍(C++)
【PTA】L1-046 整除光棍(C++)
9 1
|
20天前
|
存储 C++
【PTA】L1-043 阅览室(C++)
【PTA】L1-043 阅览室(C++)
13 1
|
1月前
|
算法 C++
c++算法学习笔记 (16) 并查集
c++算法学习笔记 (16) 并查集