算法 最小生成树之 kruskal算法+并查集
kruskal算法需要从不同连通分量中选择连结边权最小的加入到生成树中,
每个连通分量可以看成一个等价类,初始每个顶点都是一个连通分量,将新边加入类似等价类的合并过程,
因此结合并查集算法实现kruskal
int father[N];
int rank[N];
void initset(int n)
{
for(int i=1;i<=n;i++)
{
father[i]=i;// 用自身作集合值
rank[i]=0;// 秩初始值相同即可
}
}
typedef struct edge
{
int a;
int b;
int dis;
}edge;
const int M=10001;
edge e[M];// 边的数目是M
bool cmp(const edge &a,const edge &b)
{
return a.dis<b.dis;
}
// 带路径压缩
int findset(int x)
{
if(x!=father[x])
father[x]=findset(father[x]);
return father[x];// 返回的是根集合
}
void func1()
{
int n,m;
// while(cin>>n>>m)
while(~scanf("%d%d",&n,&m))
{
for(int i=0;i<m;i++)
{
// cin>>e[i].a>>e[i].b>>e[i].dis;
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].dis);
}
sort(e,e+m,cmp);
int count=0;
int sum=0;
initset(n);
for(int i=0;i<m;i++)
{
int a=e[i].a;
int b=e[i].b;
int dis=e[i].dis;
int fa=findset(a);
int fb=findset(b);
if(fa!=fb)
{
count++;
sum+=dis;
// rank merge按秩合并 ,注意合并的是fa,fb即根结点的集合值
if(rank[fa]<rank[fb])
{
father[fa]=fb;
}else
{
father[fb]=fa;
if(rank[fa]==rank[fb])
{
rank[fa]++;
}
}
}
}
if(count<n-1)
//cout<<"no"<<endl;
printf("no\n");
else
//cout<<sum<<endl;
printf("%d\n",sum);
}
}