Codeforces 278C Learning Languages(并查集)

题意抽象出来就是求联通块的个数吧,然后添加最少边使图联通。

注意所有人都不会任何语言的时候,答案是n而不是n-1。

 

#include<algorithm>

#include<iostream>

#include<cstring>

#include<fstream>

#include<sstream>

#include<vector>

#include<string>

#include<cstdio>

#include<bitset>

#include<queue>

#include<stack>

#include<cmath>

#include<map>

#include<set>

#define FF(i, a, b) for(int i=a; i<b; i++)

#define FD(i, a, b) for(int i=a; i>=b; i--)

#define REP(i, n) for(int i=0; i<n; i++)

#define CLR(a, b) memset(a, b, sizeof(a))

#define debug puts("**debug**")

#define LL long long

#define PB push_back

#define MP make_pair

#define eps 1e-8

using namespace std;



const int maxn = 111;

int n, m, k, x, fa[maxn];

set<int> lg[maxn];

set<int> :: iterator it;



int findset(int x) { return x == fa[x] ? x : fa[x] = findset(fa[x]); }



bool check(int i, int j)

{

    for(it=lg[i].begin(); it!=lg[i].end(); it++)

        if(lg[j].find(*it) != lg[j].end()) return true;

    return false;

}



int main()

{

    scanf("%d%d", &n, &m);

    int cnt = 0;

    FF(i, 1, n+1)

    {

        fa[i] = i;

        scanf("%d", &k);

        if(k == 0) cnt++;

        while(k--)

        {

            scanf("%d", &x);

            lg[i].insert(x);

        }

    }

    if(cnt == n)

    {

        printf("%d\n", n);

        return 0;

    }

    FF(i, 1, n+1) FF(j, i+1, n+1) if(check(i, j))

    {

        int x = findset(i), y = findset(j);

        if(x != y) fa[x] = y;

    }

    int ans = 0;

    FF(i, 1, n+1) if(fa[i] == i) ans++;

    printf("%d\n", ans-1);

    return 0;

}


 

 

你可能感兴趣的:(codeforces)