来源于《啊哈!算法》
//给出几个人的联系,求有几个团伙
#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;
}