CodeForces 278C Learning Languages

题目:

The "BerCorp" company has got n employees. These employees can use mapproved official languages for the formal correspondence. The languages are numbered with integers from 1 to m. For each employee we have the list of languages, which he knows. This list could be empty, i. e. an employee may know no official languages. But the employees are willing to learn any number of official languages, as long as the company pays their lessons. A study course in one language for one employee costs 1 berdollar.
Find the minimum sum of money the company needs to spend so as any employee could correspond to any other one (their correspondence can be indirect, i. e. other employees can help out translating).
Input
The first line contains two integers n and m (2 ≤ n, m ≤ 100) — the number of employees and the number of languages.
Then n lines follow — each employee's language list. At the beginning of the i-th line is integer ki
(0 ≤ ki ≤ m) — the number of languages the i-th employee knows. Next, the i-th line contains ki integers — aij (1 ≤ aij ≤ m) — the identifiers of languages the i-th employee knows. It is guaranteed that all the identifiers in one list are distinct. Note that an employee may know zero languages.
The numbers in the lines are separated by single spaces.

Output
Print a single integer — the minimum amount of money to pay so that in the end every employee could write a letter to every other one (other employees can help out translating).
Example
Input
5 5
1 2
2 2 3
2 3 4
2 4 5
1 5
Output
0
Input
8 7
0
3 1 2 3
1 1
2 5 4
2 6 7
1 3
2 7 4
1 1
Output
2
Input
2 2
1 2
0
Output
1
Hint
In the second sample the employee 1 can learn language 2, and employee 8 can learn language 4.
In the third sample employee 2 must learn language 2.

题意:
有n名员工以及m种语言,输入每名员工会多少种语言以及会的语言的编号(有可能有员工一门都不会)。现在公司可以给员工培训语言,但培训一个就要花1个币。问公司最少花多少钱可以保证这n名员工可以直接或间接(可以通过别人翻译,但翻译的人需懂那两个人的语言)进行交流。

思路:并查集。

参考代码:

#include 
#include 
#include 
#include 
#include 
using namespace std;
const int N = 100+5;

map v[N];//对应语言, 该员工是否学习了这门语言;
int par[N];
bool flag = true;//检查是否所有人都不会任何一种语言, 如果是那么就给所有人教同一门语言;//true为是;

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

void input(const int n) {
    int num;//每个人会的语言数;
    int lan;//每个人会的语言的编号;
    for (int i = 1;i <= n;++i) {
        cin >> num;
        if (num > 0) flag = false;
        for (int j = 1;j <= num;++j) {
            cin >> lan; 
            v[i][lan] = 1;//表明第i名员工会lan这门语言;
        }
    }
}
//并查集;
int finds(int x) {
    if (x == par[x]) return x;
    else return par[x] = finds(par[x]);
}

void unite(int x, int y) {
    int x1 = finds(x);
    int y1 = finds(y);
    if (x1 != y1) {
        par[y1] = x1;
    }
}

int judge(const int n, const int m) {
    if (flag == true) return n;
    for (int k = 1;k <= m;++k) {
        for (int i = 1;i <= n;++i) {
            for (int j = 1;j <= n;++j) {
                if (v[i][k] == 1 && v[j][k] == 1) {//代表他们两个都会k这门语言;
                    unite(i, j);
                }
            }
        }
    }
    //for (int i = 1;i <= n;++i) {
    //  cout << par[i] << " ";//可以直接或间接交流的人用并查集并为一个集合;
    //}
    //cout << endl;
    int ans = 0;
    for (int i = 1;i <= n;++i) {
        if (par[i] == i) {
            ++ans;
        }
    }
    //cout << ans << endl;
    //如果有合并情况, 两个集合中任意一个集合中的任意一个人学会另外一个集合中任意一个人会的语言即可;
    return ans - 1;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);
    int n, m;
    cin >> n >> m;
    init();
    input(n);
    int ans = judge(n, m);
    cout << ans << endl;
    return 0;
}

你可能感兴趣的:(CodeForces 278C Learning Languages)