并查集的板子,一开始不会做,后来多做了几道就差不多会了。
普通并查集只是顺序的节点号。但是本题给出的节点号不是顺序的,所以这里没有采用数组的方式,而是采用了map散列表的方式。当然通过dfs也可以很好的解决这个题目。通过对所有节点进行dfs。只要没有全遍历到,那就sum++;

#include<iostream>
#include<vector>
#include<map>
#include<algorithm>
using namespace std;
map<int,int> father;  //通过散列表map实现的father数组
map<int,int> height;  //记录每个节点的高度
int find(int x){
    if(father.find(x)!=father.end()){
        if(father[x]!=x)
            father[x]=find(father[x]);  //路径压缩(最后自己通过例子模拟下过程)
    }
    else{//如果还没有出现的新节点。把father设成他自己(表示根节点),height设成0
        father[x]=x; 
        height[x]=0; 
    } 
    return father[x];
} 
void Union(int a,int b){//合并函数
    a=find(a);
    b=find(b);
    if(a!=b){
        if(height[a]>height[b])
            father[b]=a;
        else if(height[b]>height[a])
            father[a]=b;
        else{
            father[a]=b;
            height[a]++;
        }
    }
}
int main()
{
    int i,j;
    while(cin>>i>>j){
        //if(i==0)break;
        Union(i,j);
    }
    int sum=0;
    for(auto it=father.begin();it!=father.end();it++){
        if(it->first==it->second)sum++;  //只要有一个父亲是本身的就说明是根节点
    } 
    cout<<sum<<endl;
    return 0;    
}