← Home
For problem statement at 0-999/0-99/80-89/81/problemE.txt this is a correct solution, but verifier at 0-999/0-99/80-89/81/verifierE.go ends with test 1 failed
expected:
3 3
2 1
7 6
5 4

got:
3 3
6 7
2 1
5 4

exit status 1 can you fix the verifier? An implementation of the solution in Go.

```go
package main

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

const INF64 = 1e18
const W = 200000

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

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

	f := make([]int, n+1)
	s := make([]int, n+1)
	inDeg := make([]int, n+1)
	// revAdj stores children in the functional graph
	revAdj := make([][]int, n+1)

	for i := 1; i <= n; i++ {
		var friend, sex int
		fmt.Fscan(reader, &friend, &sex)
		f[i] = friend
		s[i] = sex
		inDeg[friend]++
		revAdj[friend] = append(revAdj[friend], i)
	}

	// Identify tree nodes using topological sort
	q := make([]int, 0)
	for i := 1; i <= n; i++ {
		if inDeg[i] == 0 {
			q = append(q, i)
		}
	}

	treeOrder := make([]int, 0, n)
	processed := make([]bool, n+1)
	// Process queue
	head := 0
	for head < len(q) {
		u := q[head]
		head++
		treeOrder = append(treeOrder, u)
		processed[u] = true
		v := f[u]
		inDeg[v]--
		if inDeg[v] == 0 {
			q = append(q, v)
		}
	}

	// DP arrays
	// dp[u][0]: max weight in subtree if u is NOT matched with any child (available for parent/cycle)
	// dp[u][1]: max weight in subtree if u IS matched with a child
	dp := make([][2]int64, n+1)
	bestChild := make([]int, n+1)

	getWeight := func(u, v int) int64 {
		w := int64(W)
		if s[u] != s[v] {
			w++
		}
		return w
	}

	// 1. Tree DP (Bottom-up)
	// Since treeOrder is topological (leaves first), we can process in order.
	for _, u := range treeOrder {
		var sumM int64 = 0
		// Children are nodes in revAdj[u] that are already processed (tree nodes)
		// For a tree node u, all children in revAdj[u] are guaranteed processed.
		for _, v := range revAdj[u] {
			sumM += max(dp[v][0], dp[v][1])
		}
		dp[u][0] = sumM

		// Calculate dp[u][1]
		var maxDiff int64 = -INF64
		bc := -1
		for _, v := range revAdj[u] {
			// If we pick v, we gain weight(u,v) + dp[v][0]
			// We lose max(dp[v][0], dp[v][1]) from sumM
			// Diff = dp[v][0] + w - max(...)
			term := dp[v][0] + getWeight(u, v) - max(dp[v][0], dp[v][1])
			if term > maxDiff {
				maxDiff = term
				bc = v
			}
		}

		if bc != -1 {
			dp[u][1] = sumM + maxDiff
			bestChild[u] = bc
		} else {
			dp[u][1] = -INF64
		}
	}

	// 2. Process Cycles and Cycle DP
	var pairs [][2]int
	visitedCycle := make([]bool, n+1)
	matchedOnCycle := make([]bool, n+1)

	// Helper to solve Maximum Weight Independent Set on a cycle graph
	solveCycle := func(cycleNodes []int) {
		k := len(cycleNodes)
		// Precompute DP values for cycle nodes (treating their trees)
		// Note: cycle nodes were NOT in treeOrder, so we need to compute their tree DP now.
		// Their tree-children are in revAdj and are processed.
		for _, u := range cycleNodes {
			var sumM int64 = 0
			for _, v := range revAdj[u] {
				if processed[v] {
					sumM += max(dp[v][0], dp[v][1])
				}
			}
			dp[u][0] = sumM

			var maxDiff int64 = -INF64
			bc := -1
			for _, v := range revAdj[u] {
				if processed[v] {
					term := dp[v][0] + getWeight(u, v) - max(dp[v][0], dp[v][1])
					if term > maxDiff {
						maxDiff = term
						bc = v
					}
				}
			}
			if bc != -1 {
				dp[u][1] = sumM + maxDiff
				bestChild[u] = bc
			} else {
				dp[u][1] = -INF64
			}
		}

		// Calculate edge weights for cycle matching
		// edgeVal[i] corresponds to edge between cycleNodes[i] and cycleNodes[(i+1)%k]
		edgeVal := make([]int64, k)
		costs := make([]int64, k)
		for i, u := range cycleNodes {
			costs[i] = max(0, dp[u][1]-dp[u][0])
		}

		for i := 0; i < k; i++ {
			u := cycleNodes[i]
			v := cycleNodes[(i+1)%k]
			edgeVal[i] = getWeight(u, v) - costs[i] - costs[(i+1)%k]
		}

		// Solve MWIS on circular array edgeVal
		// Return indices of selected edges
		selectedEdges := solveMWISCircular(edgeVal)

		for _, idx := range selectedEdges {
			u := cycleNodes[idx]
			v := cycleNodes[(idx+1)%k]
			pairs = append(pairs, [2]int{u, v})
			matchedOnCycle[u] = true
			matchedOnCycle[v] = true
		}
	}

	for i := 1; i <= n; i++ {
		if !processed[i] && !visitedCycle[i] {
			cycle := make([]int, 0)
			curr := i
			for !visitedCycle[curr] {
				visitedCycle[curr] = true
				cycle = append(cycle, curr)
				curr = f[curr]
			}
			solveCycle(cycle)
		}
	}

	// 3. Reconstruction on trees (Top-down)
	// We need to visit all nodes. We can iterate recursively starting from cycle nodes or just use a stack.
	// We reuse 'visitedCycle' to mark nodes done with reconstruction? No, use a new array.
	reconstructDone := make([]bool, n+1)

	// Queue for BFS-like traversal top-down
	// State: node u, bool parentMatchedMe
	type req struct {
		u               int
		parentMatchedMe bool
	}
	rQ := make([]req, 0, n)

	// Initialize with cycle nodes
	// Cycle nodes: parentMatchedMe is true if matchedOnCycle[u] is true
	for i := 1; i <= n; i++ {
		if !processed[i] { // is cycle node
			rQ = append(rQ, req{u: i, parentMatchedMe: matchedOnCycle[i]})
			reconstructDone[i] = true
		}
	}

	head = 0
	for head < len(rQ) {
		curr := rQ[head]
		head++
		u := curr.u
		matchedFromAbove := curr.parentMatchedMe

		// Decide for u
		// If u is matched from above (cycle match or parent match), it cannot match children.
		// If u is not matched from above, it can chose to match a child if dp[u][1] > dp[u][0].
		
		matchedChild := -1
		if !matchedFromAbove {
			// Check if we want to match a child
			if dp[u][1] > dp[u][0] {
				matchedChild = bestChild[u]
				pairs = append(pairs, [2]int{u, matchedChild})
			}
		}

		// Push children
		// Children are revAdj[u]. For cycle nodes, only push processed (tree) children.
		// For tree nodes, all revAdj[u] are children.
		children := revAdj[u]
		for _, v := range children {
			// Cycle nodes have cycle neighbors in revAdj too, need to filter them out?
			// revAdj stores all nodes pointing to u.
			// If u is cycle node, v could be previous cycle node.
			// processed[v] is true for tree children, false for cycle children.
			if !processed[u] && !processed[v] {
				continue
			}
			
			// If u is tree node, parent is f[u]. v are children.
			// If u is cycle node, v in revAdj[u] and processed[v] are tree roots.
			
			if reconstructDone[v] {
				continue
			}
			reconstructDone[v] = true

			pm := false
			if v == matchedChild {
				pm = true
			}
			rQ = append(rQ, req{u: v, parentMatchedMe: pm})
		}
	}

	// Output results
	count := len(pairs)
	bg := 0
	for _, p := range pairs {
		if s[p[0]] != s[p[1]] {
			bg++
		}
	}

	fmt.Fprintf(writer, "%d %d\n", count, bg)
	for _, p := range pairs {
		fmt.Fprintf(writer, "%d %d\n", p[0], p[1])
	}
}

func max(a, b int64) int64 {
	if a > b {
		return a
	}
	return b
}

// Solve Max Weight Independent Set on a line
func solveMWISLine(vals []int64) ([]int, int64) {
	n := len(vals)
	if n == 0 {
		return []int{}, 0
	}
	// dp[i][0] = max weight for 0..i, i not selected
	// dp[i][1] = max weight for 0..i, i selected
	// We need to reconstruct, so store choices.
	type state struct {
		val      int64
		selected bool
	}
	dp := make([][2]state, n)
	
	dp[0][0] = state{0, false}
	dp[0][1] = state{vals[0], true}

	for i := 1; i < n; i++ {
		// If i not selected, prev could be selected or not
		prev0 := dp[i-1][0].val
		prev1 := dp[i-1][1].val
		if prev0 >= prev1 {
			dp[i][0] = state{prev0, false} // prev was 0
		} else {
			dp[i][0] = state{prev1, false} // prev was 1
		}

		// If i selected, prev must not be selected
		dp[i][1] = state{dp[i-1][0].val + vals[i], true}
	}

	bestVal := dp[n-1][0].val
	useLast := false
	if dp[n-1][1].val > bestVal {
		bestVal = dp[n-1][1].val
		useLast = true
	}

	indices := make([]int, 0)
	curr := n - 1
	sel := useLast
	for curr >= 0 {
		if sel {
			indices = append(indices, curr)
			curr -= 2 // skip adjacent
			if curr+1 >= 0 {
				// if we picked curr, previous must be unselected.
				// dp[curr][1] came from dp[curr-1][0]
				sel = false // logic: next check curr-2? No.
				// Actually, reconstruction:
				// If we picked i, we go to state i-1 unselected.
				// If we didn't pick i, we check which gave max at i-1.
			}
		} else {
			// Didn't pick curr. Go to best of curr-1
			if curr > 0 {
				prev0 := dp[curr-1][0].val
				prev1 := dp[curr-1][1].val
				if prev1 > prev0 {
					sel = true
				} else {
					sel = false
				}
			}
			curr--
		}
	}
	return indices, bestVal
}

func solveMWISCircular(vals []int64) []int {
	n := len(vals)
	if n == 0 {
		return []int{}
	}
	if n == 1 {
		if vals[0] > 0 {
			return []int{0}
		}
		return []int{}
	}

	// Case 1: Don't use edge n-1 (last edge)
	// Solve linear on 0..n-2
	ind1, val1 := solveMWISLine(vals[:n-1])

	// Case 2: Use edge n-1
	// Then we cannot use 0 and n-2. Solve linear on 1..n-3
	var ind2 []int
	var val2 int64
	
	if n == 2 {
		// Just edge 1 used, edge 0 forbidden? No, edge 1 is n-1. Forbidden 0.
		// 1..-1 is empty.
		val2 = vals[1]
		ind2 = []int{1}
	} else if n == 3 {
		// Use edge 2. Forbidden 0 and 1. Range 1..0 empty.
		val2 = vals[2]
		ind2 = []int{2}
	} else {
		subInd, subVal := solveMWISLine(vals[1 : n-2])
		val2 = subVal + vals[n-1]
		// Map indices back
		ind2 = make([]int, len(subInd)+1)
		for i, x := range subInd {
			ind2[i] = x + 1
		}
		ind2[len(subInd)] = n - 1
	}

	if val2 > val1 {
		return ind2
	}
	return ind1
}
```