(1) 在图G=(V,E)(V表示顶点,E表示边)中,从集合V中任取一个顶点(例如取顶点v0)放入集合U中,这时U={v0},集合T(E)为空。
(2) 从v0出发寻找与U中顶点相邻(另一顶点在V中)权值最小的边的另一顶点v1,并使v1加入U。即U={v0,v1},同时将该边加入集合T(E)中。
(3) 重复(2),直到U = V为止。
opt[i],flag[i]。如此反复,直到取到v-1条边为止。
AC代码:
//采用prim算法求最小生成树
#include <stdio.h>
int main(void)
{
//数组origin存放原始数据,max_distance存放矩阵中的最大值,result存放最小生成树的最大边
//opt存放节点和最小生成树之间的最小距离
int n,i,j,count,origin[500][500],opt[500],max_distance=0,min,vertex,result=0;
//flag判断是否已经加入到最小生成树中
bool flag[500];
scanf("%d",&count);
while(count-->0)
{
scanf("%d",&n);
result=0; //result清零
//输入origin,并记录矩阵中的最大值
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%d",&origin[i][j]);
if(origin[i][j]>max_distance)
max_distance=origin[i][j];
}
}
//0号节点加入到生成树中,当前最小距离为origin[0][i]的值
for(i=0;i<n;i++)
opt[i]=origin[0][i];
//flag初始化,0节点先加入生成树中,为true,其他为false
flag[0]=true;
for(i=1;i<n;i++)
flag[i]=false;
for(i=1;i<n;i++) //循环n-1次,获得n-1条边
{
min=max_distance+1;
for(j=0;j<n;j++)
{
if(!flag[j]&&min>opt[j])
{
//获得不在生成树中的最小的边,记录节点
min=opt[j];
vertex=j;
}
}
//更新result和该节点的flag
if(result<min)
result=min;
flag[vertex]=true;
//修改每个节点的opt
for(j=0;j<n;j++)
{
if(!flag[j])
opt[j]=origin[j][vertex]>opt[j]?opt[j]:origin[j][vertex];
}
}
printf("%d/n",result);
}
return 1;
}
PKU1258Agri-Net和2485基本上是一模一样,把result改为result+=min就过了,就不多说了。
相似类型的题目还有:http://acm.pku.edu.cn/JudgeOnline/problem?id=2395 (注意有重边,所以每次输入一条边都要判断它是否是这两个点的最小边。。)