← Home
```go
package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
	"sort"
)

var reader *bufio.Reader
var writer *bufio.Writer

type Edge struct {
	u, v, w int
}

type DSU struct {
	parent []int
	size   []int
}

func NewDSU(n int) *DSU {
	d := &DSU{
		parent: make([]int, n+1),
		size:   make([]int, n+1),
	}
	for i := 0; i <= n; i++ {
		d.parent[i] = i
		d.size[i] = 1
	}
	return d
}

func (d *DSU) Find(x int) int {
	for d.parent[x] != x {
		d.parent[x] = d.parent[d.parent[x]]
		x = d.parent[x]
	}
	return x
}

func (d *DSU) Union(x, y int) (int, int) {
	px, py := d.Find(x), d.Find(y)
	if px == py {
		return px, 0
	}
	sx, sy := d.size[px], d.size[py]
	if sx < sy {
		px, py = py, px
	}
	d.parent[py] = px
	d.size[px] += d.size[py]
	return px, sx * sy
}

func main() {
	reader = bufio.NewReader(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	var n, m int
	fmt.Fscan(reader, &n, &m)

	a := make([]int, n+1)
	for i := 1; i <= n; i++ {
		fmt.Fscan(reader, &a[i])
	}

	edges := make([]Edge, m)
	for i := 0; i < m; i++ {
		var u, v int
		fmt.Fscan(reader, &u, &v)
		w := int(math.Min(float64(a[u]), float64(a[v])))
		edges[i] = Edge{u, v, w}
	}

	// Sort edges in decreasing order of weight (minimum of endpoints)
	sort.Slice(edges, func(i, j int) bool {
		return edges[i].w > edges[j].w
	})

	// We use Kruskal's in reverse (maximum spanning tree approach)
	// f(p,q) = max over all paths of min animal count along path
	// This equals the minimum edge weight on the maximum spanning tree path
	// where edge weight = min(a[u], a[v])
	// Actually, we want maximum spanning tree

	dsu := NewDSU(n)
	totalSum := 0.0

	for _, e := range edges {
		_, pairs := dsu.Union(e.u, e.v)
		if pairs > 0 {
			totalSum += float64(e.w) * float64(pairs)
		}
	}

	// Handle disconnected components - but problem says zoo is connected
	// so all pairs should be covered

	ans := totalSum * 2.0 / float64(n*(n-1))
	fmt.Fprintf(writer, "%.6f\n", ans)
}
```