卡码网 53.寻宝(Kruskal算法,804)

0 阅读1分钟

题目

image.png

image.png

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)条边数,说明选完了。