[HBU-DS] 7-5 tribes (and search Collection)

Keywords: C++ data structure leetcode Binary tree

7-5 tribes (20 points)

subject

In a community, everyone has his own small circle and may belong to many different circles of friends at the same time. We think that all friends of friends are in one tribe, so please count how many disjoint tribes there are in a given community? And check whether any two people belong to the same tribe.

Input format:

The input gives a positive integer N (≤ 10e ^ 4) on the first line, which is the number of known small circles. Then N lines, each giving a small circle of people in the following format:
K P[1] P[2] ⋯ P[K]
Where k is the number of people in the small circle, and P[i] (i=1,..., K) is the number of everyone in the small circle. Here, everyone's number starts from 1, and the maximum number will not exceed 10e# 4.
The next line gives a non negative integer Q (≤ 10e ^ 4), which is the number of queries. Then line Q, each line gives the number of a pair of people queried.

Output format:

First, output the total number of people in this community and the number of disjoint tribes in one row. Then, for each query, if they belong to the same tribe, output Y in one row, otherwise output N.

Input example:

4
3 10 1 2
2 3 4
4 1 5 7 8
3 9 6 4
2
10 5
3 7
1
2
3
4
5
6
7
8

Output example:

10 2
Y
N

Problem solution

First record the first version (bug version, pay attention to the problems), see the positive solution, and skip directly
For classification, the first step is to use and query the set, so that each element can easily find the representative element - > dictionary

#include <bits/stdc++.h>
using namespace std;
map<int,int> father;
int sum;

void input(int size)
{
    vector<int> circle;
    int f=-1;
    circle.resize(size);
    for(int i=0;i<size;i++)
    {
        cin >> circle[i];
        if(father.count(circle[0]) != 0)
        {
            if(f!=-1 && father[f]!=f)
                f=circle[i];
            while(father[f]!=f)
                f=father[f];
        }
    }
    if(f==-1) 
    {
        f=circle[0];
        sum++;
    }
    for(int i=0;i<size;i++)
        father[circle[i]] = f;
}

int main()
{
    int n;
    cin >> n;
    sum=0;
    for(int i=0;i<n;i++)
    {
        int num;
        cin >> num;
        input(num);
    }
    cout << father.size() << " " << sum << endl;
    int wheel;
    cin >> wheel;
    int a,b;
    while(wheel--)
    {
        cin >> a >> b;
        if(father[a]==father[b]) cout << "Y";
        else cout << "N";
        cout << endl;
    }
}

Problem: missing updates to previously recorded values

Learn from the great God's blog: 👉 Using set to write and query sets
Query set template:

int fa[max],flag[max]={0};
int find(int x)
{
    if(fa[x] == x) return x;
    else fa[x] = find(fa[x]);
}

void Union(int a,int b)
{
    int fatherA = find(a);
    int fatherB = find(b);
    if(fatherA!=fatherB)
        fa[fatherB] = fatherA;
}

To solve this grouping problem, do not store it according to its grouping, but directly put it into a large group
If you encounter the problem of "class de duplication" of duplicate data, use set directly
Learn from the great God code and bring some notes that you can understand

#include<bits/stdc++.h>
using namespace std;
#define max 10005
int fa[max],flag[max]={0};
set<int> s;

int find(int x)
{
    if(fa[x] == x)  return x;
    else return fa[x] = find(fa[x]);
}

void Union(int a,int b)
{
    int fatherA = find(a);
    int fatherB = find(b);
    if(fatherA!=fatherB)
        fa[fatherB] = fatherA;
}

int main()
{
    ios::sync_with_stdio(0);
    int n;
    cin >> n;
    for(int i=0; i<max; i++)  //initialization
    {
        fa[i]=i;   //The parent node of each element is itself
        flag[i]=0;  //Tag with flag array
    }
    for(int i=0;i<n;i++)
    {
        int k;
        int p[max];
        cin >> k >> p[0];  //k total data of each row, p[0] as the root node, stored separately
        s.insert(p[0]);

        for(int j=1;j<k;j++)
        {
            cin >> p[j];  //Enter another node
            s.insert(p[j]);  //Each time you enter one, you put one into the collection
            Union(p[0],p[j]);  //Abstract the function Union, merge operations, and set the parent node of the current node as the first node
        }
    }
    set<int>::iterator it;
    int num=0;
    int q;   //Number of groups to compare
    int q1,q2;  //Data to be compared
    for(it=s.begin();it!=s.end();it++)
    {
        if(flag[find(*it)] == 0)   //See if the representative element has been found
        {
            num++;
            flag[find(*it)] = 1; 
        }
    }
    cout << s.size() << " " << num << endl;
    cin >> q;
    for(int i=0;i<q;i++)
    {
        cin >> q1 >> q2;
        if(find(q1) == find(q2))  cout << "Y";
        else cout << "N";
        cout << endl;
    }
    return 0;
}

Posted by delorian on Sat, 20 Nov 2021 11:29:49 -0800