算法流程:知道一个图所有边的权值,从小到大排序,排序以后从头到尾,看这条边连通的点如果不连通,就加上这条边的权值,否则直接跳过
结构体中:u是起点 v是终点 w是边权,
struct edge{
int u,v,w;
};
edge edges[MAXM];
首先按照边权从小到大排序,将边从小到大开始按照并查集判断联通性,如果不连通,加上此时这条边的边权,这也就意味着这是两点之间的最小路径了,然后合并这两点,如果已经联通呢,就直接跳过
void krusal(int n,int m)
{
sort(edges,edges+m,cmp);//先排序
int ans=0,count=0,maxn=0;
for(int i=0;i<m;i++){
int u=find(edges[i].u);
int v=find(edges[i].v);
if(u!=v){//不连通加上此时的权值
merge(u,v);
ans+=edges[i].w;
}else{//否则跳过即可
continue;
}
}
printf("%d\n",ans);
}
输出最小生成树的权值。
模板如下:(要注意数组大小)
const int MAXN=2e3+50;
const int MAXM=1e4+50;
void init(){
for(int i=0;i<=MAXN;i++){
f[i]=i;
}
}
struct edge{
int u,v,w;
};
edge edges[MAXM];
bool cmp(edge a,edge b)
{
return a.w<b.w;
}
int f[MAXN];
//并查集
int find(int x)
{
if(x==f[x]){
return x;
}else{
f[x]=find(f[x]);
return f[x];
}
}
void merge(int a,int b)
{
int t1=find(a);
int t2=find(b);
if(t1!=t2){
f[t2]=t1;
}
return ;
}
//克鲁斯 卡尔算法
void krusal(int n,int m)
{
sort(edges,edges+m,cmp);//先排序
int ans=0,count=0;
for(int i=0;i<m;i++){
int u=find(edges[i].u);
int v=find(edges[i].v);
if(u!=v){//不连通加上此时的权值
merge(u,v);
ans+=edges[i].w;
}else{//否则跳过即可
continue;
}
}
printf("%d\n",ans);
}