题目
26年8月4日(首刷看解)
package main
import "fmt"
var(
v,e int
INF=10001
)
func prim(n int ,graph [][]int)int{
minDist:=make([]int,n+1)
for i:=1;i<=v;i++{
minDist[i]=INF
}
visited:=make([]bool,v+1)//之后到时间系统学一下int,map,slice
minDist[1]=0
//寻找距离最小生成树最近的节点
for i:=1;i<v;i++{
cur:=-1
for j:=1;j<=v;j++{
if !visited[j]&&(cur==-1||minDist[j]<minDist[cur]){
cur=j
}
}
visited[cur]=true
//更新minDist距离
for j:=1;j<=v;j++{
if !visited[j]&&graph[cur][j]<minDist[j]{
minDist[j]=graph[cur][j]
}
}
//会覆盖i
}
total:=0
for _,v:=range minDist{
total+=v
}
return total
}
func main(){
fmt.Scanf("%d %d",&v,&e)
graph:=make([][]int,v+1)
for i:=range graph{
graph[i]=make([]int,v+1)
for j:=0;j<v+1;j++{
graph[i][j]=INF
}//没有初始化为INF
}
for i:=0;i<e;i++{
var v1,v2,val int
fmt.Scanf("%d %d %d",&v1,&v2,&val)
graph[v1][v2]=val
graph[v2][v1]=val
//无向图
}
res:=prim(v,graph)
fmt.Println(res)
}
思路
prim算法,着重于节点,用来解决最小生成树的问题。
三部曲
1.寻找距离最小树最近的节点
第一个节点:初始化第一个点任意选一个就行,这里把cur=-1,于是在接下来的比较,cur被赋值为1,在后续的minDist比较中,距离都是INF,所以就第一个节点加入队列。
其他节点:其他节点距离cur的值更新后,进行比较minDist,其中最小的就是距离最小树最近的节点。这里距离最近就是权值,有点像贪心,每一步选局部最优。
外层循环一共要确定n条边。
2.最近节点加入最小树
加入节点其实就是确立cur,并且标记visited的过程,后续根据cur进行更新距离
3.更新未选入节点距离最小树的距离
更新其实就是判断是否graph[cur][j]<minDist[j]。
所以prim算法的核心就是维护minDist,拿到每一步的最优解,而且在每找到最近节点后加入,需要更新minDist(有可能加入cur后最小的距离会更新,也有可能没更新)。从而以节点为核心,找到总权值最小的路线
错误点:没有初始化所有边为INF,无向图没考虑到双向的garph表赋值