prime算法原理
1.首先清空树,任取一个顶点加入生成树。
2.在那些一个顶点在生成树李,另一个顶点不在生成树里德边中,选取边权最小的一条边,把这条边的另一个顶点加入生成树。
3.重复步骤2,直到所有的顶点均加入了生成树。
如图所示:
代码:
int map[max][max];
int vis[max];
int d[max];
int prime()
{
int sum=0;
int index=1; //先将顶点1加入生成树
vis[1]=1; //标记顶点1
for(int i=0;i<m;i++) //将与顶点1相连的边的权值赋给d数组
{
d[i]=map[index][i];
}
for(int i=1;i<m;i++)
{
int min=MAX; //MAX为定义的无穷大
for(int j=0;j<m;j++) //找边权最小值
{
if(!vis[j] && d[j]<min)
{
min=d[j];
index=j;
}
}
vis[index]=1;//标记掉(把index加入生成树)
sum+=min;
for(int j=0;j<m;j++)//更新边权
{
if(!vis[j] && d[j]>map[index][j])
d[j]=map[index][j];
}
}
return sum;
}
int main()
{
/*要在主函数中先将map数组定义为无穷大,
将vis数组清空,然后在输入顶点与边权*/
for(int i=0;i<max;i++)
{
for(int j=0;j<max;j++)
{
map[i][j]=MAX;
}
}
memset(vis,0,sizeof(vis));
}
Kruskal算法
原理:先将子图看成一个只含有n个顶点的不含边的图,各个顶点看成是各自树的根节点。
从边集中选取一条权值最小的边,判断该边的两个顶点是否分属不同的树,若是则将其加入子图,然后将这两个顶点分别所在的树合成一棵树;若不是,则说明这两个点已在一颗树上,不可取。(用到了并查集)
代码:
int father[max];
int rank[max];
struct node
{
//将边的边权、起点、终点
int val,start,end;
}edge[边的最多的条数];
void make()//初始化
{
for(int i=0;i<n;i++)
{
father[i]=i;
rank[i]=1;
}
}
int find(int x)//找根节点
{
int i,j=x;
while(j!=father[j])
{
j=father[j];
}
while(x!=j)
{
i=father[x];
father[x]=j;
x=i;
}
return j;
}
void union(int x,int y)
{
x=find(x);
y=find(y);
if(x==y)
return;
if(rank[x]<rank[y])//合并
{
father[x]=find(y);
}
else
{
if(rank[x]==rank[y])
{
rank[x]++;
}
father[y]=find(x);
}
}
int Kruskal(int n)
{
int sum=0;
make();
for(int i=0;i<n;i++)//从边权最小的边开始加入图中
{
if(find(edge[i].start)!=find(edge[i].end))
{
union(edge[i].start,edge[i].end);
sum+=edge[i].val;
}
}
return sum;
}
bool cmp(node a,node b)
{
return a.val<b.val;
}
int main()
{
//输入边的边权,起点,终点
//在主函数内将边按边权从小到大排序
sort(edge,edge+边的条数,cmp);
int ans=Kruskal(n);//n为边的数量
}