1. 程式人生 > >BZOJ3296:Learning Languages(簡單並查集)

BZOJ3296:Learning Languages(簡單並查集)

3296: [USACO2011 Open] Learning Languages

Time Limit: 5 Sec  Memory Limit: 128 MB
Submit: 436  Solved: 239
[Submit][Status][Discuss]

Description

農夫約翰的N(2 <= N<=10,000)頭奶牛,編號為1.. N,一共會流利地使用M(1<= M <=30,000)種語言,編號從1  .. M.,第i頭,會說K_i(1 <= K_i<= M)種語言,即L_i1, L_i2,..., L_{iK_i} (1 <= L_ij <= M)。 FJ的奶牛 不太聰明,所以K_i的總和至多為100,000。兩頭牛,不能直接交流,除非它們都會講某一門語言。然而,沒有共同 語言的奶牛們,可以讓其它的牛給他們當翻譯。換言之,牛A和B可以談話,當且僅當存在一個序列奶牛T_1,T_2, ...,T_k,A和T_1都會說某一種語言,T_1和T_2也都會說某一種語言……,並且T_k和B會說某一種語言。農夫約翰 希望他的奶牛更加團結,所以他希望任意兩頭牛之間可以交流。他可以買書教他的奶牛任何語言。作為一個相當節 儉的農民,FJ想要購買最少的書籍,讓所有他的奶牛互相可以說話。幫助他確定:*他必須購買的書籍的最低數量

Input

*第1行:兩個用空格隔開的整數:N和M *第2..N+1行:第i+1行描述的牛i的語言,K_i+1個空格隔開的整數: K_iL_i1 L_i2,...,L_I{K_i}。

Output

*第1行:一個整數,FJ最少需要購買的書籍數量

Sample Input

3 3
2 3 2
1 2
1 1

Sample Output

1
//給三號牛買第二本書即可

HINT

Source

Silver

 

思路:我們把每總語言看成一個連通塊,讓會這麼語言的與它連通,那麼最後結果就是連通塊的個數-1;

#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=200010;
int fa[maxn],ans,vis[maxn];
int find(int x){
    if(x!=fa[x]) return fa[x]=find(fa[x]);
    return fa[x];
}
int main()
{
    int N,M,L,x;
    scanf("%d%d",&N,&M);
    rep(i,
1,M) fa[i+N]=i+N; rep(i,1,N) { scanf("%d",&L); scanf("%d",&x); fa[i]=x+N; rep(j,2,L){ scanf("%d",&x); int fu=find(x+N),fv=find(i); fa[fv]=fu; } } rep(i,1,N) { x=find(i); if(vis[x]!=-1) ans++,vis[x]=-1; } printf("%d\n",ans-1); return 0; }