文心一言 VS 讯飞星火 VS chatgpt (332)-- 算法导论23.1 1题

news2024/11/15 12:58:36

一、设(u,v)是连通图G中的一条权重最小的边,证明:边(u,v)为图G的某棵最小生成树中的一条边。如果要写代码,请用go语言。

文心一言:

为了证明边(u,v)是图G的某棵最小生成树中的一条边,我们可以使用反证法结合最小生成树的性质来进行证明。

证明过程

假设边(u,v)不是图G的任何一棵最小生成树中的边。

  1. 考虑所有最小生成树:设 T T T是图G的一棵最小生成树,且 T T T中不包含边(u,v)。

  2. 找到替换边:由于图G是连通的,且(u,v)是G中的一条边,那么在T中必然存在一条从u到v的路径(因为T是连通的)。我们可以选择这条路径上的一条边,记为(x,y),使得将(x,y)从T中移除并添加(u,v)之后,图仍然是连通的。

  3. 考虑权重变化:由于(u,v)是G中权重最小的边,且假设它是所有连接u和v的路径中权重最小的(否则我们可以选择更小的那条边作为(u,v)),因此有 w ( u , v ) ≤ w ( x , y ) w(u,v) \leq w(x,y) w(u,v)w(x,y),其中 w ( e ) w(e) w(e)表示边e的权重。

  4. 构造新的生成树:将边(x,y)从T中移除并添加边(u,v),我们得到一个新的无环连通图,记为 T ′ T' T。由于T是生成树,移除一条边后添加一个不同的边,结果仍然是生成树。

  5. 比较权重:由于 w ( T ′ ) = w ( T ) − w ( x , y ) + w ( u , v ) w(T') = w(T) - w(x,y) + w(u,v) w(T)=w(T)w(x,y)+w(u,v),且已知 w ( u , v ) ≤ w ( x , y ) w(u,v) \leq w(x,y) w(u,v)w(x,y),因此 w ( T ′ ) ≤ w ( T ) w(T') \leq w(T) w(T)w(T)

  6. 矛盾:由于我们假设T是最小生成树,其权重是最小的,但我们已经构造了一个权重不大于T的生成树 T ′ T' T,这与T是最小生成树的假设相矛盾。

因此,我们的假设——边(u,v)不是图G的任何一棵最小生成树中的边——是错误的。所以,边(u,v)必然是图G的某棵最小生成树中的一条边。

Go语言代码实现(概念性)

由于Go语言本身不直接提供图论算法的库,以下代码仅为概念性示例,展示如何开始构建或考虑一个图及其最小生成树的问题,而不直接实现完整的Kruskal或Prim算法:

package main

import (
    "fmt"
    "container/heap"
)

// Edge represents an edge in the graph
type Edge struct {
    u, v, weight int
}

// ByWeight implements sort.Interface for []Edge based on the weight field.
type ByWeight []Edge

func (a ByWeight) Len() int           { return len(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 }

// 伪代码:假设我们有一个Edge的切片,我们想要找到最小生成树
func findMinSpanningTree(edges []Edge, n int) []Edge {
    // 这里应使用Kruskal或Prim算法,但仅展示如何排序边
    h := &ByWeight{edges...}
    heap.Init(h)

    // 假设的实现...
    // 需要一个并查集来检查循环
    // 伪代码结束

    // 返回结果(这里仅为示例)
    return []Edge{{}} // 返回一个空的Edge切片,实际应返回最小生成树的边
}

func main() {
    // 示例边
    edges := []Edge{{0, 1, 10}, {0, 2, 6}, {0, 3, 5}, {1, 3, 15}, {2, 3, 4}}
    n := 4 // 节点数

    mst := findMinSpanningTree(edges, n)
    fmt.Println("Edges in MST:", mst) // 实际输出需要实现完整算法
}

注意:这个Go代码示例并未真正实现最小生成树的算法,而是展示了如何开始考虑这个问题,特别是如何对边进行排序。要实现完整的Kruskal或Prim算法,你需要实现并查集来检查循环,或者使用适当的数据结构来追踪已包含在生成树中的边和节点。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

讯飞星火:

首先,我们需要理解最小生成树的概念。在图论中,一个连通图的最小生成树是一个子图,它包含了图中的所有顶点,并且所有边的权重之和最小。这个子图是一个树,也就是说它是一个无环的连通子图。

假设(u,v)是连通图G中的一条权重最小的边,那么我们可以证明这条边一定属于图G的某棵最小生成树中。这是因为:

  1. 如果(u,v)不在最小生成树中,那么我们可以将其添加到最小生成树中,得到一个新的生成树。由于(u,v)是权重最小的边,将其添加到新的生成树中不会增加总权重,因此新的生成树仍然是最小生成树。这与我们的假设矛盾,所以(u,v)必须属于最小生成树。

  2. 如果(u,v)已经在最小生成树中,那么我们可以通过移除其他边来尝试构建更小的生成树。但是,如果我们移除了(u,v),那么将无法保持图的连通性,因为(u,v)是唯一连接两个不同连通分量的边。因此,在这种情况下,我们不能通过移除(u,v)来构建更小的生成树,所以(u,v)必须属于最小生成树。

至于Go语言代码,我们可以使用Prim算法或Kruskal算法来找到最小生成树。这里给出一个使用Prim算法的示例代码:

package main

import (
	"fmt"
	"math"
)

type Edge struct {
	u, v, weight int
}

func minKey(key []int, mstSet []bool, V int) int {
	min := math.MaxInt32
	minIndex := -1

	for v := 0; v < V; v++ {
		if key[v] < min && mstSet[v] == false {
			min = key[v]
			minIndex = v
		}
	}

	return minIndex
}

func printMST(parent []int, graph [][]Edge, V int) {
	fmt.Println("Edge \tWeight")
	for i := 1; i < V; i++ {
		fmt.Printf("%d - %d \t%d 
", parent[i], i, graph[i][parent[i]].weight)
	}
}

func primMST(graph [][]Edge, V int) {
	key := make([]int, V)
	parent := make([]int, V)
	mstSet := make([]bool, V)

	for i := 0; i < V; i++ {
		key[i] = math.MaxInt32
		parent[i] = -1
	}

	key[0] = 0
	parent[0] = -1

	for count := 0; count < V-1; count++ {
		u := minKey(key, mstSet, V)
		mstSet[u] = true

		for v := 0; v < V; v++ {
			if graph[u][v].weight > 0 && mstSet[v] == false && graph[u][v].weight < key[v] {
				parent[v] = u
				key[v] = graph[u][v].weight
			}
		}
	}

	printMST(parent, graph, V)
}

func main() {
	V := 5
	graph := make([][]Edge, V)
	for i := range graph {
		graph[i] = make([]Edge, V)
	}

	graph[0][1] = Edge{0, 1, 2}
	graph[0][3] = Edge{0, 3, 6}
	graph[1][2] = Edge{1, 2, 3}
	graph[1][3] = Edge{1, 3, 8}
	graph[1][4] = Edge{1, 4, 5}
	graph[2][4] = Edge{2, 4, 7}
	graph[3][4] = Edge{3, 4, 9}

	primMST(graph, V)
}

这段代码实现了Prim算法,可以找到给定图的最小生成树。在这个例子中,我们创建了一个包含5个顶点的图,并添加了一些边。运行代码后,我们可以看到输出的最小生成树中的边。

360智脑:

为了证明边(u, v)是图G的某棵最小生成树中的一条边,我们可以使用Kruskal算法来构建最小生成树。Kruskal算法的基本思想是按边的权重从小到大排序,然后逐个添加边到生成树中,只要这条边不会形成环。

证明过程如下:

  1. 假设:假设(u, v)不是任何最小生成树的一部分。

  2. 构造一棵最小生成树T:我们可以通过删除一条权重比(u, v)大的边(e1, e2),然后添加(u, v)来构造一棵新的生成树T’。这样做的结果是,新的生成树T’的权重总和不会比原来的生成树大。

  3. 验证T’是生成树:由于(u, v)是权重最小的边,且G是连通图,添加(u, v)不会形成环。因此,T’仍然是一个生成树。

  4. 矛盾:这与我们的假设(u, v)不是任何最小生成树的一部分相矛盾。因此,边(u, v)必须是图G的某棵最小生成树中的一条边。

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

type Edge struct {
    u, v int
    weight int
}

type UnionFind struct {
    parent []int
}

func NewUnionFind(n int) *UnionFind {
    parent := make([]int, n)
    for i := range parent {
        parent[i] = i
    }
    return &UnionFind{parent}
}

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, rootY := uf.Find(x), uf.Find(y)
    if rootX != rootY {
        uf.parent[rootX] = rootY
    }
}

func kruskalAlgorithm(edges []Edge, n int) []Edge {
    sort.Slice(edges, func(i, j int) bool {
        return edges[i].weight < edges[j].weight
    })

    uf := NewUnionFind(n)
    mst := make([]Edge, 0, n-1)

    for _, edge := range edges {
        u, v := edge.u, edge.v
        if uf.Find(u) != uf.Find(v) {
            uf.Union(u, v)
            mst = append(mst, edge)
        }
    }

    return mst
}

func main() {
    // 示例图的边集合
    edges := []Edge{
        {0, 1, 10},
        {0, 2, 6},
        {0, 3, 5},
        {1, 3, 15},
        {2, 3, 4},
    }
    n := 4 // 图的顶点数

    mst := kruskalAlgorithm(edges, n)
    for _, edge := range mst {
        fmt.Printf("Edge: (%d, %d), Weight: %d\n", edge.u, edge.v, edge.weight)
    }
}

这段代码实现了Kruskal算法,用于找到图的最小生成树。通过这个算法,我们可以证明边(u, v)是图G的某棵最小生成树中的一条边。

智谱清言:

为了证明边(u,v)是图G的某棵最小生成树中的一条边,我们可以使用反证法。

假设边(u,v)不在图G的任何一棵最小生成树中。那么,我们可以按照以下步骤进行证明:

1.假设T是图G的一棵最小生成树。

2.将边(u,v)添加到T中,由于T已经是一棵树,添加边(u,v)后会形成一个环。

3.在这个环中,必然存在一条边(x,y),其权重不小于边(u,v)(因为(u,v)是权重最小的边)。

4.如果我们从T中移除边(x,y),并添加边(u,v),则得到的新树T’仍然是一棵生成树,并且权重不会增加,因为(u,v)的权重不大于(x,y)。

5.这与T是最小生成树的假设矛盾,因此边(u,v)必须在图G的某棵最小生成树中。

下面是使用Go语言实现的Prim算法,该算法可以找到图G的一棵最小生成树,并且会包含边(u,v):

package main
import (
	"fmt"
	"container/heap"
)
// 边结构体
type Edge struct {
	from   int
	to     int
	weight int
}
// 边的优先队列
type EdgeHeap []Edge
func (h EdgeHeap) Len() int           { return len(h) }
func (h EdgeHeap) Less(i, j int) bool { return h[i].weight < h[j].weight }
func (h EdgeHeap) Swap(i, j int)      { h[i], h[j] = h[j], h[i] }
func (h *EdgeHeap) Push(x interface{}) {
	*h = append(*h, x.(Edge))
}
func (h *EdgeHeap) Pop() interface{} {
	old := *h
	n := len(old)
	x := old[n-1]
	*h = old[0 : n-1]
	return x
}
// Prim算法实现
func prim(graph [][]Edge) []Edge {
	n := len(graph)
	visited := make([]bool, n)
	minHeap := &EdgeHeap{}
	heap.Init(minHeap)
	heap.Push(minHeap, Edge{from: 0, to: 0, weight: 0}) // 从节点0开始
	var mst []Edge
	for minHeap.Len() > 0 {
		edge := heap.Pop(minHeap).(Edge)
		if visited[edge.to] {
			continue
		}
		visited[edge.to] = true
		if edge.from != edge.to {
			mst = append(mst, edge)
		}
		for _, nextEdge := range graph[edge.to] {
			if !visited[nextEdge.to] {
				heap.Push(minHeap, nextEdge)
			}
		}
	}
	return mst
}
func main() {
	// 示例图,使用邻接表表示
	graph := [][]Edge{
		{{1, 1, 4}, {7, 7, 8}},
		{{0, 0, 4}, {7, 7, 11}, {2, 2, 8}},
		{{1, 1, 8}, {8, 8, 2}, {3, 3, 7}, {5, 5, 4}},
		{{2, 2, 7}, {5, 5, 14}, {4, 4, 9}},
		{{3, 3, 9}, {5, 5, 10}},
		{{2, 2, 4}, {3, 3, 14}, {4, 4, 10}, {6, 6, 2}},
		{{5, 5, 2}, {7, 7, 1}, {8, 8, 6}},
		{{0, 0, 8}, {1, 1, 11}, {6, 6, 1}, {8, 8, 7}},
		{{2, 2, 2}, {6, 6, 6}, {7, 7, 7}},
	}
	mst := prim(graph)
	for _, edge := range mst {
		fmt.Printf("Edge from %d to %d with weight %d\n", edge.from, edge.to, edge.weight)
	}
}

这段代码实现了Prim算法,并输出了最小生成树的边。在这个算法执行过程中,如果(u,v)是权重最小的边,那么它一定会被包含在最终的最小生成树中。

天工:

要证明边(u, v)是连通图G某棵最小生成树中的一条边,我们可以通过反证法来证明。假设(u, v)不是G的任何最小生成树的边,那么在所有最小生成树中,必有一棵最小生成树T不包含边(u, v)。

由于G是连通的,且(u, v)不在T中,但T是生成树,那么一定存在一条从u到v的路径,这条路径不包含边(u, v)。这条路径上必然包含了至少一条边,其权重至少不小于(u, v)的权重,否则(u, v)就不可能是权重最小的边。我们从这条路径中选择一条边(e),其权重大于或等于(u, v)的权重。

现在,我们从T中移除边(e),并加入边(u, v)。移除边(e)不会改变T的连通性,因为u和v之间仍然有一条路径(即原先的路径去掉边(e)再加上边(u, v))。加入边(u, v)不会形成环,因为T中原本不含边(u, v)。因此,这样得到的新图T’仍然是生成树。

关键在于,移除边(e)并加入边(u, v)不会增加生成树的总权重,因为(u, v)的权重小于或等于边(e)的权重。这意味着T’也是一个最小生成树,这与我们开始的假设(即(u, v)不在任何最小生成树中)矛盾。

因此,我们的假设是错误的,边(u, v)必定是连通图G的某棵最小生成树中的一条边。

Go语言实现

虽然这个证明是理论的,但我们可以用Go语言实现Kruskal算法来构建最小生成树,并验证这个结论。Kruskal算法会保证权重最小的边(u, v)被加入到最小生成树中,如果它不会形成环。

package main

import (
	"fmt"
	"sort"
)

type Edge struct {
	u, v, weight int
}

type UnionFind struct {
	parent []int
}

func (uf *UnionFind) New(n int) {
	uf.parent = make([]int, n)
	for i := range uf.parent {
		uf.parent[i] = i
	}
}

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) {
	px, py := uf.Find(x), uf.Find(y)
	if px != py {
		uf.parent[px] = py
	}
}

func kruskal(edges []Edge, n int) int {
	sort.Slice(edges, func(i, j int) bool {
		return edges[i].weight < edges[j].weight
	})

	uf := UnionFind{}
	uf.New(n)
	mstWeight := 0

	for _, e := range edges {
		if uf.Find(e.u) != uf.Find(e.v) {
			uf.Union(e.u, e.v)
			mstWeight += e.weight
		}
	}

	return mstWeight
}

func main() {
	edges := []Edge{
		{0, 1, 2},
		{0, 2, 1},
		{1, 2, 3},
		{1, 3, 4},
		{2, 3, 2},
	}
	n := 4
	fmt.Println("Weight of the Minimum Spanning Tree is:", kruskal(edges, n))
}

这段代码实现了Kruskal算法,通过排序和并查集来构建最小生成树。可以看到,权重最小的边会优先被加入到生成树中,验证了我们的证明。


## chatgpt:

要证明边(u,v)为图G的某棵最小生成树中的一条边,可以使用Kruskal或Prim算法来构建最小生成树。下面是用Go语言实现Prim算法的示例代码:

```go
package main

import (
	"fmt"
	"math"
)

// 辅助函数:找到未包含在最小生成树中的顶点集合中具有最小键值的顶点索引
func findMinKeyIndex(key []float64, mstSet []bool, V int) int {
	min := math.Inf(1)
	minIndex := -1

	for v := 0; v < V; v++ {
		if !mstSet[v] && key[v] < min {
			min = key[v]
			minIndex = v
		}
	}

	return minIndex
}

// 使用Prim算法构建最小生成树
func primMST(graph [][]float64, V int) {
	parent := make([]int, V) // 存储最小生成树中每个顶点的父节点索引
	key := make([]float64, V) // 存储顶点到最小生成树的键值(边权重)
	mstSet := make([]bool, V) // 记录顶点是否包含在最小生成树中

	for i := 0; i < V; i++ {
		key[i] = math.Inf(1)
		mstSet[i] = false
	}

	key[0] = 0     // 第一个顶点作为起始顶点
	parent[0] = -1 // 起始顶点没有父节点

	for count := 0; count < V-1; count++ {
		u := findMinKeyIndex(key, mstSet, V) // 找到具有最小键值的顶点索引
		mstSet[u] = true                     // 将该顶点包含在最小生成树中

		// 更新与u相邻的顶点的键值和父节点索引
		for v := 0; v < V; v++ {
			if graph[u][v] != 0 && !mstSet[v] && graph[u][v] < key[v] {
				parent[v] = u
				key[v] = graph[u][v]
			}
		}
	}

	fmt.Println("边(u,v)为图G的某棵最小生成树中的一条边:", parent)
}

func main() {
	V := 4 // 图G的顶点数

	graph := [][]float64{
		{0, 2, 0, 6},
		{2, 0, 3, 8},
		{0, 3, 0, 0},
		{6, 8, 0, 0},
    }
    
    primMST(graph, V)
}

在这个示例代码中,我们使用了邻接矩阵来表示图G,其中权重为0表示两个顶点之间没有直接连接。通过Prim算法构建最小生成树,并输出每个顶点的父节点索引数组parent,即可得到边(u,v)是否在最小生成树中的信息。

kimi:

要证明边 (u, v) 是图 G 的某棵最小生成树中的一条边,我们可以利用最小生成树的性质和构造过程来证明。

证明:

  1. 最小生成树的定义:最小生成树是一棵包含图 G 中所有顶点的树,并且它的边的总权重是所有这样的树中最小的。

  2. 边 (u, v) 的特性:由于 (u, v) 是权重最小的边,这意味着在所有连接两个不同顶点的边中,(u, v) 的权重是最小的。

  3. 贪心算法构造最小生成树:在构造最小生成树的过程中,我们可以使用贪心算法,即每次选择当前图中权重最小的边,并且这条边不会导致图中出现环。这样逐步添加边,直到所有顶点都被包含在树中。

  4. 边 (u, v) 的选择:在贪心算法的每一步中,由于 (u, v) 是权重最小的边,它一定会在某个时刻被选中,除非添加这条边会导致环。但是,由于 (u, v) 是权重最小的边,它连接的两个顶点 u 和 v 在被连接之前不可能通过其他边相连(否则 (u, v) 就不是权重最小的边了),因此添加 (u, v) 不会导致环。

  5. 结论:因此,边 (u, v) 一定会被包含在图 G 的某棵最小生成树中。

Go 语言代码示例

以下是一个使用 Kruskal 算法构造最小生成树的 Go 语言代码示例。Kruskal 算法是一种贪心算法,它适用于边权重的图。

package main

import (
	"fmt"
)

type Edge struct {
	Weight int
	V      int
	U      int
}

type Graph struct {
	Edges []Edge
}

type UnionFind struct {
	parent []int
	rank   []int
}

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 int, y int) {
	xRoot, yRoot := uf.Find(x), uf.Find(y)
	if xRoot == yRoot {
		return
	}
	if uf.rank[xRoot] < uf.rank[yRoot] {
		uf.parent[xRoot] = yRoot
	} else if uf.rank[xRoot] > uf.rank[yRoot] {
		uf.parent[yRoot] = xRoot
	} else {
		uf.parent[yRoot] = xRoot
		uf.rank[xRoot]++
	}
}

func (g *Graph) KruskalMST() []Edge {
	uf := &UnionFind{parent: make([]int, len(g.Edges)), rank: make([]int, len(g.Edges))}
	for i := range uf.parent {
		uf.parent[i] = i
	}
	sortedEdges := make([]Edge, len(g.Edges))
	copy(sortedEdges, g.Edges)
	sort.Slice(sortedEdges, func(i, j int) bool {
		return sortedEdges[i].Weight < sortedEdges[j].Weight
	})
	mst := []Edge{}
	for _, edge := range sortedEdges {
		if uf.Find(edge.U) != uf.Find(edge.V) {
			uf.Union(edge.U, edge.V)
			mst = append(mst, edge)
		}
	}
	return mst
}

func main() {
	g := Graph{
		Edges: []Edge{
			{Weight: 10, U: 0, V: 1},
			{Weight: 15, U: 0, V: 2},
			{Weight: 10, U: 1, V: 2},
			{Weight: 35, U: 2, V: 0},
			{Weight: 20, U: 1, V: 3},
			{Weight: 25, U: 2, V: 3},
		},
	}
	mst := g.KruskalMST()
	fmt.Println("Edges in the minimum spanning tree:", mst)
}

这段代码定义了一个图,使用 Kruskal 算法来找到最小生成树,并打印出构成最小生成树的边。在这个算法中,边 (u, v) 一定会被考虑,并且如果它不会导致环,它就会被包含在最小生成树中。

混元:

为了证明边(u,v)是图G的某棵最小生成树中的一条边,我们可以使用Kruskal算法的思想。Kruskal算法是一种贪心算法,用于找到图的最小生成树。它的工作原理是按照边的权重顺序(从小到大)处理每条边,如果这条边连接的两个顶点属于不同的连通分量,则将这条边加入到最小生成树中,并合并这两个顶点所在的连通分量。

根据Kruskal算法的步骤,我们可以得出以下结论:

  1. 在处理权重最小的边(u,v)时,由于它是权重最小的边,所以在它之前不会有任何边被加入到最小生成树中。
  2. 当我们尝试加入边(u,v)时,由于它是第一条被考虑的边,此时图G中的所有顶点都处于不同的连通分量中。
  3. 因此,边(u,v)必然连接两个不同的连通分量,所以它可以被加入到最小生成树中。
  4. 加入边(u,v)后,它所在的连通分量将会包含u和v两个顶点,且由于(u,v)是最小权重边,后续加入的任何边都不可能替换掉它,因为没有比它更小的权重边可以连接这两个顶点。

基于以上分析,我们可以得出结论:权重最小的边(u,v)必然是图G的某棵最小生成树中的一条边。

下面是使用Go语言实现的Kruskal算法示例代码,用于验证上述结论:

package main

import (
	"fmt"
	"sort"
)

// 定义边的结构体
type Edge struct {
	Src, Dest, Weight int
}

// 定义并查集的结构体
type Subset struct {
	Parent, Rank int
}

// Kruskal算法实现
func KruskalMST(edges []Edge, V int) []Edge {
	result := make([]Edge, 0)
	subsets := make([]Subset, V)
	for i := range subsets {
		subsets[i] = Subset{Parent: i, Rank: 0}
	}

	// 按照边的权重进行排序
	sort.Slice(edges, func(i, j int) bool {
		return edges[i].Weight < edges[j].Weight
	})

	e := 0 // result[] 的索引
	i := 0 // edges[] 的索引
	for e < V-1 && i < len(edges) {
		next_edge := edges[i]
		i++

		x := find(subsets, next_edge.Src)
		y := find(subsets, next_edge.Dest)

		if x != y {
			result = append(result, next_edge)
			union(subsets, x, y)
			e++
		}
	}

	return result
}

// 并查集查找函数
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) {
	xroot := find(subsets, x)
	yroot := find(subsets, y)

	if subsets[xroot].Rank < subsets[yroot].Rank {
		subsets[xroot].Parent = yroot
	} else if subsets[xroot].Rank > subsets[y---

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2074098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

09 复合查询

前面的查询都是对一张表进行查询&#xff0c;但这远远不够 基本查询回顾 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J select * from EMP where (sal>500 or job‘MANAGER’) and ename like ‘J%’; 按照部门号升序而雇员的…

免费用的写作神器:一键自动生成文章,提升内容创作效率!

传统的写作过程往往耗时耗力&#xff0c;从构思、调研到撰写、修改&#xff0c;每一步都需要创作者亲力亲为。免费写作神器的出现&#xff0c;犹如一场及时雨&#xff0c;为创作者提供了强大的支持。它利用先进的算法和自然语言处理技术&#xff0c;能够在短时间内生成高质量的…

了解Redis数据持久化(中)

3.5写时复制 Redis在使用RDB方式进行持久化时&#xff0c;会用到写时复制机制。写时复制的效果: bgsave子进程相当于复制了原始数据&#xff0c;而主线程仍然可以修改原来的数据。 对Redis来说&#xff0c;主线程fork出bgsave子进程后&#xff0c;bgsave子进程实际是复制了主线…

初识C语言指针(5)

目录 1. 回调函数 2. qsort函数 2.1 qsort函数的基本参数 2.2 qsort函数的使用 2.3 qsort排序结构体类型数据 结语 1. 回调函数 什么是回调函数呢&#xff1f;回调函数就是⼀个通过函数指针调⽤的函数。 如果你把函数的指针&#xff08;地址&#xff09;作为参数传递给另…

超分CAMixerSR 使用笔记

目录 超分CAMixerSR 笔记 自己改进的图例示例: 修改目录: 设置预训练模型: 超分CAMixerSR 笔记 自己改进的图例示例: 修改目录: codes/basicsr改为codes/basicsr_m 设置预训练模型: path:pretrain_network_g: F:\project\chaofen\CAMixerSR-main\pretrained_mode…

解决html中文乱码问题

在head上面添加 <% page contentType"text/html;charsetUTF-8" language"java" %>

【Three.js基础学习】19.Custom models with Blender

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 前言 blender模型资源:【blender】一个汉堡包-CSDN博客 一、代码 import ./style.css import * as THREE from three import { OrbitControls } from three/examples/jsm/co…

集成mybatis-plus框架

文章目录 1.新建一个sun_frame数据库并创建user表2.新建一个sun-common-mybatisplus模块1.maven项目2.添加依赖 3.sun-user集成mybatis-plus1.配置application.yml2.修改架构&#xff0c;由sun-user模块引入需要的公共模块3.代码目录结构4.mapper&#xff1a;po查&#xff0c;p…

SQLSugar进阶使用:高级查询与性能优化

文章目录 前言一、高级查询1.查所有2.查询总数3.按条件查询4.动态OR查询5.查前几条6.设置新表名7.分页查询8.排序 OrderBy9.联表查询10.动态表达式11.原生 Sql 操作 &#xff0c;Sql和存储过程 二、性能优化1.二级缓存2.批量操作3.异步操作4.分表组件&#xff0c;自动分表5.查询…

了解Redis数据持久化(上)

Redis常用作缓存&#xff0c;提高读取相应性能。Redis如果宕机可以从后端数据库里恢复数据&#xff0c;但是会出现的问题&#xff1a; 数据是从慢速数据库里获取数据&#xff0c;速度比不上从Redis缓存中获取。频繁访问数据库会给数据库造成压力。 处理宕机的方法就是&#xf…

Go 调用Rust函数

Go 调用Rust函数 在golang 中,go可以引用c代码&#xff0c;和c共舞&#xff0c;也就是cgo.在一些包里就能看到cgo的身影&#xff0c;gopcap(引用了libpcap),go-sqlite(引用了libsqlite).毕竟c是"万物之主"嘛.本文利用cgo实现go调rust函数 这是一个rust demo用于生成…

【Docker】Docker学习03 | Docker的volume

本文首发于 ❄️慕雪的寒舍 1. 引入 在docker的基本知识讲解中&#xff0c;提到了docker镜像是由一层一层文件系统构成的。这一系列文件系统是一系列的只读层。当我们创建一个容器的时候&#xff0c;Docker会读取镜像&#xff08;只读&#xff09;&#xff0c;并在镜像的顶部再…

SpringBoot集成google登陆快速入门Demo

1.为何要使用 Google 账号登录 借助“使用 Google 账号登录”功能&#xff0c;您可通过安全性备受信赖的 Google 账号&#xff0c;轻松快捷地在网上登录和注册网站与应用。该功能可消除您对密码的依赖&#xff0c;从而降低使用密码带来的困扰和安全风险。 2.环境准备 登录 G…

【IEEE出版】第八届电气、机械与计算机工程国际学术会议(ICEMCE 2024,10月25-27)

由西京学院主办&#xff0c;AEIC学术交流中心协办&#xff0c;中国科学技术大学、深圳大学、浙江工业大学等校联合支持的第八届电气、机械与计算机工程国际学术会议&#xff08;ICEMCE 2024&#xff09;将于2024年10月25日至27日在西安举办。 本次会议主要围绕“电气”、"…

【文档】软件项目售后服务标准文档参考(word原件)

软件售后服务方案的售后服务范围广泛&#xff0c;涵盖了多个方面&#xff0c;以确保客户在使用软件过程中得到全面、及时的支持。具体来说&#xff0c;这些服务范围通常包括以下几个核心内容&#xff1a; 技术支持服务维护与更新服务培训与教育服务定制化服务数据管理与服务客户…

[C语言]一、C语言基础(函数)

G:\Cpp\C语言精讲 6. 函数 6.1函数的基本使用 6.1.1 为什么需要函数 《街霸》游戏中&#xff0c;每次人物出拳、出脚或跳跃等动作都需要编写50-80行的代码&#xff0c;在每次出拳、出脚或跳跃的地方都需要重复地编写这50-80行代码&#xff0c;这样程序会变得很臃肿&#xff…

[学习笔记]深度学习详解-Datawhale学习组

第三章&#xff1a;深度学习基础 3.1 局部极小值与鞍点 3.1.1 临界点及其种类 优化神经网络时&#xff0c;使用梯度下降法&#xff0c;遇到梯度为0的点&#xff0c;训练就停了下来&#xff0c;损失也不再下降。 这个梯度为0的点&#xff0c;可以称为临界点。 临界点可以细分…

在挫折感中遇见更好的自己

你是如何克服编程学习中的挫折感的&#xff1f; 编程学习之路上&#xff0c;挫折感就像一道道难以逾越的高墙&#xff0c;让许多人望而却步。然而&#xff0c;真正的编程高手都曾在这条路上跌倒过、迷茫过&#xff0c;却最终找到了突破的方法。你是如何在Bug的迷宫中找到出口的…

ssrf+redisssrf+fastcgi

curl支持很多协议&#xff0c;有FTP, FTPS, HTTP, HTTPS, GOPHER, TELNET, DICT, FILE以及LDA ssrfredis dict被禁用了用&#xff08;?urlhttp://172.19.0.3端口&#xff09;来探测一下端口吧 172.19.0.3主机只开放一个80端口 看看内网还有其他服务器没 这里可以看到内网还有…

Ai+若依(代码生成 -- 树表“有层级关系的”):【03篇】

代码生成 代码生成器,根据数据库表结构自动生成前后端CRUD代码提供三种生成模板:单表、树表、主子表(一对多)现在来说说树表,主子表 树表: 例如:公司==》部门==》员工 层级关系的这种 主子表: 例如: 数据之间存在一对多,比如菜品和口味表 一个菜品可以多个口味 自动化…