最小生成树
1.Kruskal算法
首先选择最短的边,再选择次短的边,直到连通,若两个点已经用过就不再用了
判断两个顶点是否连通:并查集
int father[maxn+1];
int getf(int v)
{
if(father[v]==v)
return v;
else
return father[v]=getf(father[v]);
}
int merge(int u,int v)
{
int t1=getf(u);
int t2=getf(v);
if(t1!=t2)
{
f[t2]=f[t1];
return 1;
}
return 0;
}
Kruskal核心部分:
for(int i=1;i<=n;i++)
f[i]=1;
for(int i=1;i<=m;i++)
{
if(merge(e[i].u,e[i].v])
{
count++;
sum+=e[i].w;
}
if(count==n-1)
break;
}
cout<<sum<<endl;
2.Prim算法
把所有的点分为两部分:已经生成加入集合的,还未加入的,每次寻找离所有生成集合中任意一点最近的点加入生成的集合
为了找点,类似Dijkstra算法,利用辅助数组,不过更新方法变为靠近生成的点组成的集合,而不是某一固定点
代码为://假设从1号点开始
for(int i=1;i<=n;i++)
dis[i]=e[1][i];
book[1]=1;
count++;
While(count<n)
{
min=INF;
for(int i=1;i<=n;i++)
{
if(book[i]==0&&dis[i]<min)
{
min=dis[i];
mark=i;
}
book[mark]=1;
count++;
sum+=dis[mark];
for(int j=1;j<=n;j++)
if(boo[j]==0&&dis[j]>a[mark][j]
dis[j]=a[mark][j];
}
}
cout<<sum<<endl;