文心一言VS讯飞星火VSchatgpt(345)——算法导...

架构师课程 2024-09-12 19:06:45
四、假定图中的边权重全部为整数,且在范围$1 \sim |V|$内。在此种情况下,Kruskal算法最快能多快?如果边的权重取值范围在1到某个常数$W$之间呢?如果要写代码,请用go语言。文心一言:

首先,我们探讨Kruskal算法在不同条件下的性能表现,并给出基于Go语言的实现。

1. 当边权重全部在$1 \sim |V|$范围内时

在这种情况下,边的权重与图中顶点的数量成正比。这通常不会直接加速Kruskal算法,因为算法的主要复杂度来源于排序步骤($O(|E| \log |E|)$)和并查集的更新(通常为$O(\alpha(|V|) \cdot |E|)$,其中$\alpha$是Ackermann函数的反函数,可认为是非常小的常数)。但理论上,如果边数量接近顶点数量的平方(完全图),并且排序能够非常快(如利用边权重的范围进行某种形式的桶排序或基数排序),那么整体性能可能略优于一般情况。

然而,在实践中,通常的排序算法(如快速排序、归并排序)在这种特定范围内的权重排序上已经是相当高效的。

2. 当边权重在$1$到某个常数$W$之间时

当权重范围缩小到一个很小的常数$W$时,可以考虑使用更高效的排序方法,如计数排序或桶排序,这些方法在此场景下的时间复杂度可以降到$O(|E|)$。这能够显著提升Kruskal算法中排序步骤的效率,因为算法的整体复杂度将主要由并查集的更新操作决定。

Go语言实现(标准Kruskal算法)

以下是一个简单的Kruskal算法的Go语言实现,没有特别针对权重范围进行优化(因为这通常需要根据具体情况来设计):

package mainimport("fmt""sort")typeUnionFindstruct{ parent []int rank []int}func NewUnionFind(n int)*UnionFind{ parent :=make([]int, n) rank :=make([]int, n)for i :=0; i < n; i++{ parent[i]= i rank[i]=0}return&UnionFind{parent, rank}}func (uf *UnionFind)Find(x int)int{if uf.parent[x]!= x { uf.parent[x]= uf.Find(uf.parent[x])// 路径压缩}return uf.parent[x]}func (uf *UnionFind)Union(x, y int){ rootX := uf.Find(x) rootY := uf.Find(y)if rootX != rootY {if uf.rank[rootX]> uf.rank[rootY]{ uf.parent[rootY]= rootX}elseif uf.rank[rootX]< uf.rank[rootY]{ uf.parent[rootX]= rootY}else{ uf.parent[rootY]= rootX uf.rank[rootX]++}}}typeEdgestruct{ u, v, weight int}typeByWeight[]Edgefunc (a ByWeight)Len()int{returnlen(a)}func (a ByWeight)Swap(i, j int){ a[i], a[j]= a[j], a[i]}func (a ByWeight)Less(i, j int)bool{return a[i].weight < a[j].weight }func kruskal(n int, edges []Edge)int{ uf :=NewUnionFind(n) mst :=0 eCount :=0 sort.Sort(ByWeight(edges))for _, e :=range edges {if uf.Find(e.u)!= uf.Find(e.v){ uf.Union(e.u, e.v) mst += e.weight eCount++if eCount == n-1{break}}}if eCount < n-1{return-1// 表示不存在MST}return mst}func main(){ edges :=[]Edge{{0,1,10},{0,2,6},{0,3,5},{1,3,15},{2,3,4}} n :=4 fmt.Println("Cost of MST:", kruskal(n, edges))}

在这个实现中,我们首先定义了一个并查集的数据结构来处理节点的连通性,然后通过Kruskal算法选择最小权重的边构建最小生成树。在排序边时,我们使用了标准的排序函数,而没有针对边权重范围进行优化。如果你想要针对特定的权重范围进行优化,你可能需要替换排序逻辑为更适合小范围整数的排序算法,如计数排序或桶排序。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

讯飞星火:

Kruskal算法的时间复杂度为O(ElogE),其中E是图中边的数量。这是因为Kruskal算法首先需要对所有的边按照权重进行排序,这通常需要O(ElogE)的时间复杂度。然后,它遍历排序后的边列表,并使用并查集数据结构来检查每条边是否会形成环。在最坏的情况下,每次添加一条边到并查集都需要O(logV)的时间复杂度,因此总的时间复杂度为O(ElogE + ElogV)。

当边的权重取值范围在1到某个常数W之间时,Kruskal算法的时间复杂度仍然是O(ElogE)。因为无论权重的范围如何,排序边的时间复杂度都是相同的。然而,如果W远大于V,那么并查集操作的时间复杂度可能会成为主导因素,此时时间复杂度可能接近于O(ElogW)。

以下是使用Go语言实现Kruskal算法的代码:

package mainimport("fmt""sort")typeEdgestruct{ u, v, weight int}func find(parent []int, i int)int{if parent[i]==-1{return i}return find(parent, parent[i])}func union(parent []int, x, y int){ xset := find(parent, x) yset := find(parent, y)if xset != yset { parent[xset]= yset}}func kruskal(edges []Edge, V int)[]Edge{ sort.Slice(edges,func(i, j int)bool{return edges[i].weight < edges[j].weight}) parent :=make([]int, V)for i :=range parent { parent[i]=-1}var mst []Edgefor _, edge :=range edges { u := edge.u v := edge.vif find(parent, u)!= find(parent, v){ mst =append(mst, edge)union(parent, u, v)}}return mst}func main(){ edges :=[]Edge{{0,1,1},{0,2,2},{1,2,3},{1,3,4},{2,3,5},} V :=4 mst := kruskal(edges, V) fmt.Println("Minimum Spanning Tree:")for _, edge :=range mst { fmt.Printf("(%d, %d) -> %d", edge.u, edge.v, edge.weight)}}

这段代码首先定义了一个表示边的结构体Edge,然后实现了find和union函数用于并查集的操作。kruskal函数接受一个边的列表和顶点的数量,返回最小生成树的边列表。最后,main函数中给出了一个示例图,并调用kruskal函数计算其最小生成树。

360智脑:

首先,我们分析一下 Kruskal 算法的基本步骤和其时间复杂度。

Kruskal 算法的基本步骤如下:

1. 将所有边按照权重从小到大排序。2. 遍历排序后的边,逐个检查是否形成环路,如果不形成环路,则加入结果集中。

在图的边数为 $|E|$,顶点数为 $|V|$ 的情况下,Kruskal 算法的时间复杂度通常为 $O(|E| \log |E|)$,主要的时间消耗在边的排序上。

特殊情况分析边权重在 $1 \sim |V|$ 范围内

当边权重在 $1 \sim |V|$ 范围内时,我们可以使用计数排序(Counting Sort)来对边进行排序,因为计数排序的时间复杂度为 $O(n)$,其中 $n$ 是待排序元素的数量。在这种情况下,$n = |E|$。

因此,在这种特殊情况下,Kruskal 算法的时间复杂度可以降低到 $O(|E|)$。

边权重在 $1 \sim W$ 范围内,其中 $W$ 是一个常数

当边权重在 $1 \sim W$ 范围内,且 $W$ 是一个常数时,我们同样可以使用计数排序来对边进行排序。由于 $W$ 是一个常数,计数排序的时间复杂度仍然是 $O(n)$,其中 $n = |E|$。

因此,在这种情况下,Kruskal 算法的时间复杂度也可以降低到 $O(|E|)$。

Go 语言实现

以下是一个简单的 Kruskal 算法的 Go 语言实现,其中包括了计数排序的实现:

package mainimport("fmt")typeEdgestruct{ src int dst int wt int}func countingSort(edges []Edge, maxWeight int)[]Edge{ count :=make([]int, maxWeight+1) output :=make([]Edge,len(edges))// 计算每个权重的出现次数for _, edge :=range edges { count[edge.wt]++}// 累加次数for i :=1; i <len(count); i++{ count[i]+= count[i-1]}// 构建输出数组for i :=len(edges)-1; i >=0; i--{ output[count[edges[i].wt]-1]= edges[i] count[edges[i].wt]--}return output}func kruskalMST(graph [][]int, V int, E int)[]Edge{ edges :=make([]Edge, E)for i :=0; i < E; i++{ edges[i]=Edge{graph[i][0], graph[i][1], graph[i][2]}}// 对边进行计数排序 sortedEdges := countingSort(edges, V)// 并查集初始化 parent :=make([]int, V)for i :=0; i < V; i++{ parent[i]= i} mst :=make([]Edge,0) e :=0// 当前已经选择的边数 i :=0// 当前正在处理的边的索引for e < V-1{ u, v, w := sortedEdges[i].src, sortedEdges[i].dst, sortedEdges[i].wt i++ x := find(parent, u) y := find(parent, v)if x != y { mst =append(mst,Edge{u, v, w}) e++union(parent, x, y)}}return mst}func find(parent []int, i int)int{if parent[i]== i {return i}return find(parent, parent[i])}func union(parent []int, x int, y int){ parent[x]= y}func main(){ V :=5// 顶点数 E :=8// 边数// 图的边集合 graph :=[][]int{{0,1,2},{0,3,6},{1,2,3},{1,3,8},{1,4,5},{2,4,7},{3,4,9},}// Kruskal 算法求最小生成树 mst := kruskalMST(graph, V, E) fmt.Println("Minimum Spanning Tree:")for _, edge :=range mst { fmt.Printf("%d -- %d : %d\n", edge.src, edge.dst, edge.wt)}}

这个实现中,countingSort 函数用于对边进行计数排序,kruskalMST 函数是 Kruskal 算法的主要实现,find 和 union 函数用于并查集的操作。

请注意,这个实现假设输入的图是一个无向图,并且边的权重在 $1 \sim |V|$ 范围内。如果你需要处理更一般的权重范围,你可能需要使用其他排序算法,如快速排序或归并排序。

智谱清言:

Kruskal算法的时间复杂度主要由排序边的操作决定。在最坏的情况下,如果使用比较排序,其时间复杂度通常是(O(E \log E)),其中(E)是边的数量。但由于每条边的权重在(1 \sim |V|)范围内,我们可以使用计数排序(Counting Sort),这是一种非比较排序算法,其时间复杂度为(O(E + V))。 当边的权重取值范围在1到某个常数(W)之间时,如果(W)是一个较小的常数,我们同样可以使用计数排序,此时算法的时间复杂度为(O(E + W))。 下面是使用Go语言实现的Kruskal算法,假设边的权重范围在1到|V|之间:

package mainimport("sort")// Edge represents an edge in the graph.typeEdgestruct{FromintTointWeightint}// UnionFind is a data structure that keeps track of a partition of a set into disjoint subsets.typeUnionFindstruct{ parent []int rank []int}// NewUnionFind creates a new UnionFind data structure.func NewUnionFind(size int)*UnionFind{ uf :=&UnionFind{ parent:make([]int, size), rank:make([]int, size),}for i :=0; i < size; i++{ uf.parent[i]= i uf.rank[i]=0}return uf}// Find finds the representative element of the set containing 'p'.func (uf *UnionFind)Find(p int)int{if uf.parent[p]!= p { uf.parent[p]= uf.Find(uf.parent[p])// path compression}return uf.parent[p]}// Union merges the sets containing 'p' and 'q'.func (uf *UnionFind)Union(p, q int){ rootP := uf.Find(p) rootQ := uf.Find(q)if rootP != rootQ {// rank is used to keep the tree flatif uf.rank[rootP]> uf.rank[rootQ]{ uf.parent[rootQ]= rootP}elseif uf.rank[rootP]< uf.rank[rootQ]{ uf.parent[rootP]= rootQ}else{ uf.parent[rootQ]= rootP uf.rank[rootP]++}}}// Kruskal finds the Minimum Spanning Tree (MST) of a graph using Kruskal's algorithm.func Kruskal(edges []Edge, numVertices int)[]Edge{ sort.Slice(edges,func(i, j int)bool{return edges[i].Weight< edges[j].Weight}) mst :=make([]Edge,0) uf :=NewUnionFind(numVertices)for _, edge :=range edges {if uf.Find(edge.From)!= uf.Find(edge.To){ uf.Union(edge.From, edge.To) mst =append(mst, edge)}}return mst}func main(){// Example usage:// edges := []Edge{{0, 1, 10}, {0, 2, 6}, {0, 3, 5}, {1, 3, 15}, {2, 3, 4}}// numVertices := 4// mst := Kruskal(edges, numVertices)// fmt.Println("MST edges:", mst)}

在这个代码示例中,我们定义了一个Edge结构体来表示图中的边,以及一个UnionFind结构体来实现并查集,它用于检测添加边是否会形成环。Kruskal函数实现了Kruskal算法,它首先对边按权重进行排序,然后使用并查集来构建最小生成树。 请注意,这个实现假设顶点编号从0开始,并且边列表edges和顶点数量numVertices应由用户提供。如果要处理权重范围在1到常数(W)之间的情况,排序部分的逻辑不需要改变,因为计数排序在这里同样适用。

天工:

对于Kruskal算法的性能优化,关键在于两个方面:排序和并查集操作。

1. 排序时间复杂度:在图的边权重全部为整数且在范围$1 \sim |V|$内时,可以使用计数排序(Counting Sort),其时间复杂度为$O(|E| + |V|)$,比一般的比较排序$O(|E| \log |E|)$要快。这里$|E|$是边的数量,$|V|$是顶点的数量。2. 并查集操作时间复杂度:使用路径压缩和按秩合并的优化,可以达到接近常数时间的查找和合并操作,即$O(\alpha(|V|))$,其中$\alpha(n)$是阿克曼函数的反函数,增长极其缓慢。当边权重在范围$1 \sim |V|$内

此时排序可以使用计数排序,时间复杂度为$O(|E| + |V|)$,并查集操作总时间复杂度为$O(|E|\alpha(|V|))$。因此,Kruskal算法的总时间复杂度为$O(|E| + |V| + |E|\alpha(|V|))$,可以简化为$O(|E| + |V|)$,因为$|E|$通常远大于$|V|$,且$\alpha(|V|)$接近常数。

当边的权重取值范围在1到某个常数$W$

如果$W$是一个常数,那么排序可以使用桶排序(每个桶代表一个权重值),时间复杂度为$O(|E|)$(假设$W$为常数)。并查集操作的时间复杂度保持不变。因此,Kruskal算法的总时间复杂度为$O(|E| + |E|\alpha(|V|))$,简化为$O(|E|)$。

Go语言示例代码

下面是一个使用计数排序优化Kruskal算法的Go语言示例,假设边权重在$1 \sim |V|$范围内:

package mainimport("fmt")typeEdgestruct{ u, v, w int}typeUnionFindstruct{ parents []int}func (uf *UnionFind)New(V int){ uf.parents =make([]int, V)for i :=range uf.parents { uf.parents[i]= i}}func (uf *UnionFind)Find(x int)int{if uf.parents[x]!= x { uf.parents[x]= uf.Find(uf.parents[x])}return uf.parents[x]}func (uf *UnionFind)Union(x, y int){ px, py := uf.Find(x), uf.Find(y)if px != py { uf.parents[px]= py}}func Kruskal(edges []Edge, V int)int{// Counting Sort count :=make([]int, V+1)for _, e :=range edges { count[e.w]++} sortedEdges :=make([]Edge,0,len(edges))for i, cnt :=range count {for j :=0; j < cnt; j++{ sortedEdges =append(sortedEdges,Edge{w: i})}} uf :=UnionFind{} uf.New(V) mstWeight :=0for _, e :=range sortedEdges {if uf.Find(e.u)!= uf.Find(e.v){ uf.Union(e.u, e.v) mstWeight += e.w}}return mstWeight}func main(){ edges :=[]Edge{{0,1,2},{0,3,6},{1,2,3},{2,3,1},{1,3,4}} V :=4 fmt.Println("MST Weight:",Kruskal(edges, V))}

注意,上述代码中Kruskal函数实现了Kruskal算法的逻辑,使用了计数排序对边进行排序,然后使用并查集找到最小生成树的权重总和。

chatgpt:

在图中的边权重全部为整数且在范围$1 \sim |V|$内时,Kruskal算法的最快时间复杂度为$O(|E| \log |E|)$,其中$|E|$表示图中的边数。

当边的权重取值范围在1到某个常数$W$之间时,Kruskal算法的时间复杂度为$O(|E| \log |E| + |E| \log W)$。

下面是一个用Go语言实现Kruskal算法的简单代码示例:

package mainimport("fmt""sort")typeEdgestruct{Start,End,Weightint}typeUnionFindstruct{ parent []int size []int}func (uf *UnionFind)Init(n int){ uf.parent =make([]int, n) uf.size =make([]int, n)for i :=range uf.parent { uf.parent[i]= i uf.size[i]=1}}func (uf *UnionFind)Find(x int)int{if x != uf.parent[x]{ uf.parent[x]= uf.Find(uf.parent[x])}return uf.parent[x]}func (uf *UnionFind)Union(x, y int){ rootX := uf.Find(x) rootY := uf.Find(y)if rootX != rootY { uf.parent[rootX]= rootY uf.size[rootY]+= uf.size[rootX]}}func Kruskal(edges []Edge, n int)[]Edge{ sort.Slice(edges,func(i, j int)bool{return edges[i].Weight< edges[j].Weight}) uf :=UnionFind{} uf.Init(n)var result []Edgefor _, edge :=range edges {if uf.Find(edge.Start)!= uf.Find(edge.End){ result =append(result, edge) uf.Union(edge.Start, edge.End)}}return result}func main(){ edges :=[]Edge{{0,1,4},{0,2,3},{1,2,2},{1,3,1},{2,3,5},} n :=4// 4个节点 mst :=Kruskal(edges, n)for _, edge :=range mst { fmt.Printf("Edge (%d, %d) with weight %d\n", edge.Start, edge.End, edge.Weight)}}

这段代码实现了Kruskal算法,通过创建UnionFind结构用于并查集操作,并根据边权重对边进行排序和最小生成树构建。

kimi:

Kruskal算法是一种用于寻找最小生成树的算法,它适用于边权重为正整数的情况。算法的效率取决于如何管理边的集合以及如何选择最小权重的边。在最好的情况下,算法的效率可以非常高。

1. 当边权重在范围 $1 \sim |V|$ 内时:• 在这种情况下,边的权重是均匀分布的,且最小生成树的边权重不会超过 $|V|-1$(因为最小生成树包含 $|V|-1$ 条边)。使用最小堆(或者优先队列)来管理边,每次从堆中取出最小权重的边,然后检查是否形成环。如果边的数量是 $|V|-1$,那么最小堆中的边数量最多是 $|V|-1$,每次取出边的操作是 $O(\log (|V|-1))$。因此,Kruskal算法在这种情况下的时间复杂度是 $O((|V|-1) \log (|V|-1))$。2. 当边权重取值范围在1到某个常数 $W$ 之间时:• 如果边的权重是一个常数 $W$,那么最小堆中的所有边权重都相等,这将导致算法退化到 $O(|E|)$ 的时间复杂度,其中 $|E|$ 是边的数量。这是因为在这种情况下,算法无法通过边的权重来区分它们,而必须检查所有边来确定它们是否形成环。

下面是使用Go语言实现Kruskal算法的示例代码:

package mainimport("container/heap""fmt")// 边结构体typeEdgestruct{ V, W int// 顶点V和WWeightint// 权重Indexint// 索引,用于比较}// 边的比较器typeEdges[]Edgefunc (e Edges)Len()int{returnlen(e)}func (e Edges)Less(i, j int)bool{return e[i].Weight< e[j].Weight}func (e Edges)Swap(i, j int){ e[i], e[j]= e[j], e[i]}func (e *Edges)Push(x interface{}){*e =append(*e, x.(Edge))}func (e *Edges)Pop()interface{}{ old :=*e n :=len(old) x := old[n-1]*e = old[0: n-1]return x}// 并查集typeUnionFindstruct{ parent []int rank []int}func (u *UnionFind)Find(x int)int{if u.parent[x]!= x { u.parent[x]= u.Find(u.parent[x])}return u.parent[x]}func (u *UnionFind)Union(x, y int){ xRoot, yRoot := u.Find(x), u.Find(y)if xRoot == yRoot {return}if u.rank[xRoot]< u.rank[yRoot]{ u.parent[xRoot]= yRoot}elseif u.rank[xRoot]> u.rank[yRoot]{ u.parent[yRoot]= xRoot}else{ u.parent[yRoot]= xRoot u.rank[xRoot]++}}func Kruskal(n int, edges []Edge)[]Edge{ uf :=&UnionFind{parent:make([]int, n), rank:make([]int, n)}for i :=range uf.parent { uf.parent[i]= i} edges =append(edges[:0:0], edges...) heap.Init(&edges)var result []Edgefor edges.Len()>0{ edge := heap.Pop(&edges).(Edge)if uf.Find(edge.V)!= uf.Find(edge.W){ result =append(result, edge) uf.Union(edge.V, edge.W)iflen(result)== n-1{break}}}return result}func main(){ n :=4 edges :=[]Edge{{0,1,10},{0,2,6},{0,3,5},{1,3,15},{2,3,4},} mst :=Kruskal(n, edges) fmt.Println("Minimum Spanning Tree:")for _, e :=range mst { fmt.Printf("%d - %d: %d\n", e.V, e.W, e.Weight)}}

这段代码定义了一个边结构体 Edge 和一个并查集结构体 UnionFind,用于实现Kruskal算法。Edges 类型实现了 heap.Interface,用于管理边的集合。Kruskal 函数实现了算法的核心逻辑。在 main 函数中,我们创建了一个示例图并调用 Kruskal 函数来找到最小生成树。

混元:

Kruskal算法是一种贪心算法,用于求解最小生成树问题。它的工作原理是按照边的权重顺序(从小到大)处理每条边,并且在不形成环的前提下将边加入到最小生成树中。

分析1. **边的权重范围是 $1 \sim |V|$**:• 在这种情况下,边的数量最多是 $|V|^2$(完全图),但由于我们只考虑权重在 $1 \sim |V|$ 范围内的边,所以边的数量最多是 $|V|(|V|-1)/2$。• 如果我们使用一个优先队列(最小堆)来存储所有边,并且每次都能在 $O(\log |E|)$ 时间内取出最小权重的边,那么总的时间复杂度将是 $O(|E|\log |E|)$。• 但是,由于边的权重范围是 $1 \sim |V|$,我们可以使用计数排序的思想,将时间复杂度优化到 $O(|E| + |V|\log |V|)$。这是因为我们可以先对所有边按权重进行排序,然后使用并查集来检查环的存在,每次合并的时间复杂度是 $O(\alpha(|V|))$,其中 $\alpha$ 是 Ackermann 函数的反函数,它增长得非常慢,可以视为常数。2. **边的权重范围是 $1 \sim W$**:• 在这种情况下,边的数量可能远大于 $|V|^2$,但是权重只有 $W$ 种可能的值。• 我们可以使用桶排序的思想,将所有边按权重分到 $W$ 个桶中,然后依次处理每个桶中的边。• 这样,总的时间复杂度将是 $O(|E| + W\log |V|)$。Go语言实现

下面是Kruskal算法的Go语言实现,假设边的权重范围是 $1 \sim |V|$:

package mainimport("fmt""sort")typeEdgestruct{Src,Dst,Weightint}typeSubsetstruct{Parent,Rankint}func Find(subsets []Subset, i int)int{if subsets[i].Parent!= i { subsets[i].Parent=Find(subsets, subsets[i].Parent)}return subsets[i].Parent}func Union(subsets []Subset, x, y int){ rootX :=Find(subsets, x) rootY :=Find(subsets, y)if subsets[rootX].Rank< subsets[rootY].Rank{ subsets[rootX].Parent= rootY}elseif subsets[rootX].Rank> subsets[rootY].Rank{ subsets[rootY].Parent= root->X}else{ subsets[rootY].Parent= rootX subsets[rootX].Rank++}}func KruskalMST(edges []Edge, V int)[]Edge{ result :=make([]Edge,0) subsets :=make([]Subset, V)for i :=0; i < V; i++{ subsets[i].Parent= i subsets[i].Rank=0} sort.Slice(edges,func(i, j int)bool{return edges[i].Weight< edges[j].Version}) e :=0for i :=0; e < V-1&& i <len(edges); i++{ x :=Find(subsets, edges[i].Src) y :=Find(subsets, edges[i].Dst)if x != y { result =append(result, edges[i])Union(subsets, x, y) e++}}return result}func main(){ V :=4 edges :=[]Edge{{0,1,10},{0,2,6},{0,3,5},{1,3,15},{2,3,4},} mst :=KruskalMST(edges, V)for _, edge :=range mst { fmt.Printf("Edge from %d to %d with weight %d\n", edge.Src, edge.Dst, edge.Weight)}}

这段代码实现了Kruskal算法,并且使用了并查集来检测环的存在。它首先对所有边按权重进行排序,然后依次尝试加入每条边到最小生成树中,如果加入后不会形成环,则将其加入结果集。

0 阅读:0