AcWing 859. Kruskal算法求最小生成树 - golang 注释
原题链接
简单
作者:
望哥
,
2020-07-16 12:17:46
,
所有人可见
,
阅读 696
package main
import (
"fmt"
"bufio"
"os"
"sort"
)
const N=100010 // 1≤n≤10^5,
const M=2*100010 // 1≤m≤2∗10^5
const MaxDist = N*10000*2 // 图中涉及边的边权的绝对值均不超过10000
var (
reader=bufio.NewReader(os.Stdin)
writer=bufio.NewWriter(os.Stdout)
n,m int // 第一行包含两个整数n和m。
u,v,w int // 接下来m行,每行包含三个整数u,v,w,表示点u和点v之间存在一条权值为w的边。
edges [M]*Edge // 存放所有边
p[N] int // 并查集
)
type Edge struct{
a,b,c int
}
// kruskal算法 返回最小生成树权值
//
// 核心思想: 将所有边按照权重从小到大排序,然后依次遍历每条边, 如 a->b,如果a和b不在同一个集合,则接受此边, 并将a,b加入到同一个集合;
// 备注: kruskal算法和prim算法类似, prim算法只存在一个集合,其他点一个个加入到集合中;
// kruskal 可能同时存在多个集合,每个集合都是最小生成树,遍历过程中会将多个集合合并为一个集合,得到最终的最小生成树。
func kruskal() int{
for i:=1;i<=n;i++{
p[i] = i
}
sort.Slice(edges[:m], func(i,j int) bool {
return edges[i].c < edges[j].c
})
res:=0
cnt:=0 // 统计边数,因为通过集合合并方式组合树,只能通过统计边数看是不是将所有的点都合并到一个集合了
for i:=0;i<m;i++{
p1:=find(edges[i].a)
p2:=find(edges[i].b)
// 不在一个集合则合并
if p1!=p2 {
p[p2] = p1
res+=edges[i].c
cnt++
}
}
// 如果小于 n-1,则无法构造最小生成树
if cnt<n-1{
return -1
}
return res
}
// 并查集查询
func find(a int) int{
if p[a]==a {
return a
}
b:= find(p[a])
p[a] = b
return b
}
func main(){
fmt.Fscan(reader, &n, &m)
for i:=0;i<m;i++{
fmt.Fscan(reader, &u,&v,&w)
edges[i] = &Edge{u,v,w}
}
res:=kruskal()
// 共一行,若存在最小生成树,则输出一个整数,表示最小生成树的树边权重之和,如果最小生成树不存在则输出impossible。
if res==-1{
fmt.Println("impossible")
}else{
fmt.Println(res)
}
}