并查集 (不相交集数据结构)

来源:互联网 发布:centos开启ssh端口 编辑:程序博客网 时间:2024/05/19 14:39
来源于《啊哈!算法》//给出几个人的联系,求有几个团伙 #include<cstdio>using namespace std;int f[1000]={0},n,m,k,sum;//sum:团伙数 //初始化,数组里面存自己数组下标的编号 void init(){    int i;    for(int i=1;i<=n;i++)    f[i]=i;    return ;} //找father的递归函数,不停地找father,直到找到祖宗为止 //“擒贼先擒王”原则 int getf(int v){    if(f[v]==v)        return v;    else    {        /*路径压缩,每次在函数返回的时候,顺带把路上遇到人的“boss”改为        最后找到的祖宗编号 ,也就是boss的编号,一边提高以后找到团伙的速度         (已经知道祖宗了,不用再找,直接比较两个人的father是不是一个人就可以了) */         /*即:一直找(递归),直到找到一个father(也就是祖宗)        是自己的人,因为boss的boss是himself */        f[v]=getf(f[v]);        return f[v];    } }//合并两子集(合并两个子集的祖先即可) void merge(int v,int u){    int t1,t2;//t1,t2分别为v,u的 big boss     t1=getf(v);    t2=getf(u);    if(t1!=t2)//判断是否在一个集合中(即:判断祖先是否为同一个)     {        f[t1]=t2;        //将其中一个集合变为另一个集合的子集合         //经过路径压缩后,将f[u]根的值也赋值为v的祖先f[t1]     }     return; } //话说:从主程序阅读是一个好习惯 int main(){    int i,x,y;    scanf("%d %d",&n,&m);    //不可或缺的初始化    init();    for(i=1;i<=m;i++)    {        scanf("%d %d",&x,&y);//x,y是一伙        merge(x,y);     }     //有多少个独立的团伙    //找有多少人的 祖宗 是自己,即找有几个boss,有几个boss,就有几个团伙     for(int i=1;i<=n;i++)    {        if(f[i]==i)        sum++;     }    printf("%d\n",sum);    return 0;}

kruskal(部分)

struct node{    LL f,t,c;}e[size];bool cmp(node a,node b){    return a.c<b.c;}LL find(LL x)   //找祖先{    return fa[x]==x?x:fa[x]=find(fa[x]);}void kru(){    sort(e+1,e+m+1,cmp);    for(int i=1;i<=m;i++)   //路径压缩    {        LL fx=find(e[i].f),fy=find(e[i].t);         if(fx!=fy)         {            fa[fx]=fy;            ans+=e[i].c;        }    }    printf("%lld\n",ans);}int main(){    scanf("%lld%lld",&n,&m);    for(int i=1;i<=m;i++)    {        scanf("%lld%lld%lld",&e[i].f,&e[i].t,&e[i].c);    }    for(int i=1;i<=n;i++)   //初始化    fa[i]=i;    kru();    return 0;}