题目
26年8月4日(首刷看解)
package main
import (
"fmt"
"sort"
)
var(
v,e int
father []int
)
type Edge struct{
v1 int
v2 int
val int
}
func Kruscal(n int,edges []Edge)int{
initFather(n)
sort.Slice(edges,func(i,j int)bool{
return edges[i].val<edges[j].val
})
count:=0
total:=0
for i:=range edges{
if !issame(edges[i].v1,edges[i].v2){
join(edges[i].v1,edges[i].v2)
count++
total+=edges[i].val
if count==v-1{
//错了,边数很多,但是只需要节点少一个边
return total
}
}
}
return 0
}
func main(){
fmt.Scanf("%d %d",&v,&e)
edges:=make([]Edge,e)
for i:=0;i<e;i++{
var v1,v2,val int
fmt.Scanf("%d %d %d",&v1,&v2,&val)//忘记取地址了
edges[i].v1=v1
edges[i].v2=v2
edges[i].val=val
}
res:=Kruscal(v,edges)
fmt.Println(res)
}
func initFather(n int){
father=make([]int,n+1)
for i:=1;i<=n;i++{
father[i]=i
}
}
func find(u int)int{
if u==father[u]{
return u
}
father[u]=find(father[u])
return father[u]
}
func join(u,v int){
u=find(u)
v=find(v)
if u==v{
return
}
father[v]=u
}
func issame(u,v int)bool{
u=find(u)
v=find(v)
return u==v
}
思路
Kruscal算法,以边为核心的算法
这个算法用到了并查集的基础函数,定义一个Edge数据结构储存 边+权值,对每一条边,权值升序排列。
这样保证在后续的遍历中,优先考虑权值小的边,这样能保证总权值最小
然后在选择的时候,如果同根issame,说明之前已经选过相应的节点,那么就不用选了。边数可能有很多,但是如果选到了(节点-1)条边数,说明选完了。