← Home
An elegant and self-contained solution in Go.

```go
package main

import (
	"bufio"
	"fmt"
	"os"
)

var (
	adj     [][]int
	binom   [105][105]float64
	subSize []int
	tempDP  [55][55]float64 // temp buffer to avoid allocation
)

func init() {
	for i := 0; i <= 100; i++ {
		binom[i][0] = 1
		for j := 1; j <= i; j++ {
			binom[i][j] = binom[i-1][j-1] + binom[i-1][j]
		}
	}
}

// dp[u][s][m] stores the probability that node u absorbs a component of size s
// within its subtree, such that the component has m boundary edges connecting
// to the unabsorbed parts of the subtree.
// Note: We use a flattened or recycled structure for efficiency.
// Since creating 3D arrays is expensive, we return the 2D array [s][m] for each node.
func solve(u, p int) [55][55]float64 {
	// Base case: u itself, size 1, boundary edges 0
	var curr [55][55]float64
	curr[1][0] = 1.0
	subSize[u] = 1

	for _, v := range adj[u] {
		if v == p {
			continue
		}
		childDP := solve(v, u)
		
		// Clear tempDP
		// We only need to clear up to the new possible sizes
		newSz := subSize[u] + subSize[v]
		// Optimization: only clear the relevant range
		for i := 0; i <= newSz; i++ {
			for j := 0; j <= newSz; j++ { // bound m can be at most size
				tempDP[i][j] = 0
			}
		}

		// Convolve
		for su := 1; su <= subSize[u]; su++ {
			for mu := 0; mu <= subSize[u]; mu++ { // conservative bound for m
				if curr[su][mu] == 0 {
					continue
				}
				
				// Option 1: Do not merge v into u's component.
				// The edge (u, v) becomes a boundary edge for u's component.
				// v's internal structure probability sums to 1, so we just take weight 1.
				// s stays same, m increases by 1.
				tempDP[su][mu+1] += curr[su][mu]

				// Option 2: Merge v into u's component.
				// Iterate over valid configurations of v.
				for sv := 1; sv <= subSize[v]; sv++ {
					for mv := 0; mv <= subSize[v]; mv++ {
						if childDP[sv][mv] == 0 {
							continue
						}
						
						// Calculate merge probability factor
						// Factor F = 1 / ((k + m + 1) * binom(k + m, k))
						// where k = sv - 1 (edges in v's component)
						// m = mv (boundary edges of v's component)
						k := sv - 1
						denom := float64(k+mv+1) * binom[k+mv][k]
						prob := 0.5 / denom // 0.5 for the coin flip u wins vs v

						val := curr[su][mu] * childDP[sv][mv] * prob
						tempDP[su+sv][mu+mv] += val
					}
				}
			}
		}
		
		subSize[u] = newSz
		// Copy temp back to curr
		for i := 0; i <= subSize[u]; i++ {
			for j := 0; j <= subSize[u]; j++ {
				curr[i][j] = tempDP[i][j]
			}
		}
	}
	return curr
}

func main() {
	reader := bufio.NewReader(os.Stdin)
	var n int
	fmt.Fscan(reader, &n)

	adj = make([][]int, n+1)
	for i := 0; i < n-1; i++ {
		var u, v int
		fmt.Fscan(reader, &u, &v)
		adj[u] = append(adj[u], v)
		adj[v] = append(adj[v], u)
	}

	subSize = make([]int, n+1)
	results := make([]float64, n+1)

	// Since N <= 50, O(N^5) is acceptable. 
	// We run the DP rooted at each vertex.
	for r := 1; r <= n; r++ {
		dp := solve(r, 0)
		// The answer is the probability of forming a component of size n with 0 boundary edges.
		// Our DP already includes the factors for all internal edges and structure.
		results[r] = dp[n][0]
	}

	for i := 1; i <= n; i++ {
		fmt.Printf("%.10f\n", results[i])
	}
}
```