One day Nikita found the string containing letters "a" and "b" only. Nikita thinks that string is beautiful if it can be cut into 3 strings (possibly empty) without changing the order of the letters, where the 1-st and the 3-rd one contain only letters "a" and the 2-nd contains only letters "b".Nikita wants to make the string beautiful by removing some (possibly none) of its characters, but without changing their order. What is the maximum length of the string he can get?

The first line contains a non-empty string of length not greater than 5 000 containing only lowercase English letters "a" and "b".

Print a single integer — the maximum possible size of beautiful string Nikita can get.

NoteIt the first sample the string is already beautiful.In the second sample he needs to delete one of "b" to make it beautiful.

// Try Codeforces
// author: Leonardone @ NEETSDKASU
package main

import (
	"fmt"
)

func main() {
	var s string
	fmt.Scan(&s)
	size := len(s)
	acnt := make([]int, size+2)
	bcnt := make([]int, size+2)
	for i, c := range s {
		if c == 'a' {
			acnt[i+1] = acnt[i] + 1
			bcnt[i+1] = bcnt[i]
		} else {
			acnt[i+1] = acnt[i]
			bcnt[i+1] = bcnt[i] + 1
		}
	}
	ans := 0
	for i := 0; i <= size; i++ {
		for j := i; j <= size; j++ {
			a1 := acnt[i] - acnt[0]
			b1 := bcnt[j] - bcnt[i]
			a2 := acnt[size] - acnt[j]
			c := a1 + b1 + a2
			if c > ans {
				ans = c
			}
		}
	}
	fmt.Println(ans)
}

package main

import (
    "fmt"
    "bufio"
    "os"
    "strconv"
    "strings"
)

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

func main() {
    //io
    scanner := bufio.NewReader(os.Stdin)
    writer := bufio.NewWriter(os.Stdout)
    //---
    var s string
    fmt.Fscan(scanner, &s)
    frst := strings.Index(s, "b")
    scnd := strings.LastIndex(s, "b")

    if(frst == -1) {
        writer.WriteString(strconv.Itoa(len(s)))
        writer.Flush()
        os.Exit(0)
    }

    t := s[frst:scnd+1]
    ans := -1
    n := len(t)
    a, b := make([]int, n+1), make([]int, n+1)

    for i := 0; i < n; i++ {
        a[i+1], b[i+1] = a[i], b[i]
        if(t[i] == 'a') {
            a[i+1]++
        } else {
            b[i+1]++
        }
    }

    for i := 0; i <= n; i++ {
        for j := i; j <= n; j++ {
            x := a[i]
            y := b[j] - b[i]
            z := a[n] - a[j]
            ans = max(ans, x + y + z)
        }
    }

    writer.WriteString(strconv.Itoa(ans + len(s) - len(t)))
    writer.Flush()
}

package main

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

func main() {
	do()
}

func do() {
	s := bufio.NewScanner(os.Stdin)
	s.Split(bufio.ScanWords)
	s.Scan()
	xs := s.Text()
	n := len(xs)

	sumA := prefixSums(xs, n, 'a')
	sumB := prefixSums(xs, n, 'b')

	maxLen := -1
	for i := 0; i <= n-1; i++ {
		for j := i; j <= n; j++ {
			t := max(0, i, sumA) + max(i, j, sumB) + max(j, n, sumA)
			if t > maxLen {
				maxLen = t
			}
		}
	}
	fmt.Println(maxLen)
}

func prefixSums(xs string, n int, x byte) []int {
	ss := make([]int, n+1)
	c := 0
	for i := 0; i < n; i++ {
		if xs[i] == x {
			c++
		}
		ss[i+1] = c
	}
	return ss
}

func max(i, j int, sum []int) int {
	return sum[j] - sum[i]
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF877B(in io.Reader, out io.Writer) {
	var s []byte
	Fscan(bufio.NewReader(in), &s)
	n := len(s)
	sum := make([]int, n+1)
	for i, b := range s {
		sum[i+1] = sum[i]
		if b == 'a' {
			sum[i+1]++
		}
	}
	ans := sum[n]
	for i, b := range s {
		if b != 'b' {
			continue
		}
		for j := i; j < n; j++ {
			if s[j] != 'b' {
				continue
			}
			if s := sum[n] + j + 1 - i - 2*(sum[j+1]-sum[i]); s > ans {
				ans = s
			}
		}
	}
	Fprint(out, ans)
}

func main() { CF877B(os.Stdin, os.Stdout) }

package main

import (
    "fmt"
    "bufio"
    "os"
    "strconv"
    "strings"
)

func main() {
    //io
    scanner := bufio.NewReader(os.Stdin)
    writer := bufio.NewWriter(os.Stdout)
    //---
    var s string
    fmt.Fscan(scanner, &s)
    frst := strings.Index(s, "b")
    scnd := strings.LastIndex(s, "b")
    if(frst == -1) {
        writer.WriteString(strconv.Itoa(len(s)))
        writer.Flush()
        os.Exit(0)
    }
    //x := s[:frst]
    y := s[frst:scnd+1]
    //z := s[scnd+1:]
    ans := strings.Count(y, "a")
    ans2 := strings.Count(y, "b")
    if(ans < ans2) {
        writer.WriteString(strconv.Itoa(len(s) - ans))
    } else {
        writer.WriteString(strconv.Itoa(len(s) - ans2))
    }

    writer.Flush()
}

package main

import (
    "fmt"
    "bufio"
    "os"
    "strconv"
    "strings"
)

func min(a, b int) int {
    if(a < b) {
        return a;
    }
    return b;
}

func main() {
    //io
    scanner := bufio.NewReader(os.Stdin)
    writer := bufio.NewWriter(os.Stdout)
    //---
    var s string
    fmt.Fscan(scanner, &s)
    t := s
    _ = t
    frst := strings.Index(s, "b")
    scnd := strings.LastIndex(s, "b")

    if(frst == -1) {
        writer.WriteString(strconv.Itoa(len(s)))
        writer.Flush()
        os.Exit(0)
    }
    cnt := 0
    sz := len(s)
    ans := 9999999
    for frst != -1 {
        y := ""
        if len(s) > len(t) {
            y = t[frst:scnd+1]
        } else {
            y = s[frst:scnd+1]
        }
        ans = min(ans, min(strings.Count(y, "a"), strings.Count(y, "b")) + cnt)
        s = s[frst+1:scnd+1]
        t = t[frst:scnd]
        frst = strings.Index(s, "b")
        scnd = strings.LastIndex(s, "b")
        cnt++
    }

    writer.WriteString(strconv.Itoa(sz - ans))
    writer.Flush()
}

package main

import (
    "fmt"
    "bufio"
    "os"
    "strconv"
    "strings"
)

func min(a, b int) int {
    if(a < b) {
        return a;
    }
    return b;
}

func main() {
    //io
    scanner := bufio.NewReader(os.Stdin)
    writer := bufio.NewWriter(os.Stdout)
    //---
    var s string
    fmt.Fscan(scanner, &s)
    t := s
    _ = t
    frst := strings.Index(s, "b")
    scnd := strings.LastIndex(s, "b")

    if(frst == -1) {
        writer.WriteString(strconv.Itoa(len(s)))
        writer.Flush()
        os.Exit(0)
    }
    cnt := 0
    sz := len(s)
    ans := 9999999
    for frst != -1 {
        y := s[frst:scnd+1]
        ans = min(ans, min(strings.Count(y, "a"), strings.Count(y, "b")) + cnt)
        s = s[frst+1:scnd+1]
        frst = strings.Index(s, "b")
        scnd = strings.LastIndex(s, "b")
        cnt++
    }

    writer.WriteString(strconv.Itoa(sz - ans))
    writer.Flush()
}

package main

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

func main() {
	do()
}

func do() {
	s := bufio.NewScanner(os.Stdin)
	s.Split(bufio.ScanWords)
	s.Scan()
	xs := s.Text()
	n := len(xs)

	sumA := prefixSums(xs, n, 'a')
	sumB := prefixSums(xs, n, 'b')

	maxLen := -1
	for i := 0; i < n-1; i++ {
		for j := i; j <= n; j++ {
			t := max(0, i, sumA) + max(i, j, sumB) + max(j, n, sumA)
			if t > maxLen {
				maxLen = t
			}
		}
	}
	fmt.Println(maxLen)
}

func prefixSums(xs string, n int, x byte) []int {
	ss := make([]int, n+1)
	c := 0
	for i := 0; i < n; i++ {
		if xs[i] == x {
			c++
		}
		ss[i+1] = c
	}
	return ss
}

func max(i, j int, sum []int) int {
	return sum[j] - sum[i]
}

package main

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

func main() {
	do()
}

func do() {
	s := bufio.NewScanner(os.Stdin)
	s.Split(bufio.ScanWords)
	s.Scan()
	xs := s.Text()
	n := len(xs)

	maxLen := -1
	for i := 0; i < n-1; i++ {
		for j := i + 1; j <= n; j++ {
			if isBeautiful(xs[i:j]) && j-i > maxLen {
				maxLen = j - i
			}
		}
	}
	fmt.Println(maxLen)
}

func isBeautiful(xs string) bool {
	state := 0
	for i := 0; i < len(xs); i++ {
		switch {
		case state == 0 && xs[i] == 'a':
		case state == 0 && xs[i] == 'b':
			state = 1
		case state == 1 && xs[i] == 'a':
			state = 2
		case state == 1 && xs[i] == 'b':
		case state == 2 && xs[i] == 'a':
		case state == 2 && xs[i] == 'b':
			return false
		}
	}
	return state == 2
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF877B(in io.Reader, out io.Writer) {
	var s string
	Fscan(bufio.NewReader(in), &s)
	a := []int{}
	if s[0] == 'b' {
		a = append(a, 0)
	}
	for i, n := 0, len(s); i < n; {
		st := i
		for ; i < n && s[i] == s[st]; i++ {
		}
		a = append(a, i-st)
	}
	a = append(a, 0)
	ans := 0
	for i := 1; i < len(a); i += 2 {
		s := a[i-1] + a[i]
		if i+1 < len(a) {
			s += a[i+1]
		}
		if s > ans {
			ans = s
		}
	}
	Fprint(out, ans)
}

func main() { CF877B(os.Stdin, os.Stdout) }


This Christmas Santa gave Masha a magic picture and a pencil. The picture consists of n points connected by m segments (they might cross in any way, that doesn't matter). No two segments connect the same pair of points, and no segment connects the point to itself. Masha wants to color some segments in order paint a hedgehog. In Mashas mind every hedgehog consists of a tail and some spines. She wants to paint the tail that satisfies the following conditions:   Only segments already presented on the picture can be painted;  The tail should be continuous, i.e. consists of some sequence of points, such that every two neighbouring points are connected by a colored segment;  The numbers of points from the beginning of the tail to the end should strictly increase. Masha defines the length of the tail as the number of points in it. Also, she wants to paint some spines. To do so, Masha will paint all the segments, such that one of their ends is the endpoint of the tail. Masha defines the beauty of a hedgehog as the length of the tail multiplied by the number of spines. Masha wants to color the most beautiful hedgehog. Help her calculate what result she may hope to get.Note that according to Masha's definition of a hedgehog, one segment may simultaneously serve as a spine and a part of the tail (she is a little girl after all). Take a look at the picture for further clarifications.

First line of the input contains two integers n and m(2 ≤ n ≤ 100 000, 1 ≤ m ≤ 200 000) — the number of points and the number segments on the picture respectively.  Then follow m lines, each containing two integers ui and vi (1 ≤ ui, vi ≤ n, ui ≠ vi) — the numbers of points connected by corresponding segment. It's guaranteed that no two segments connect the same pair of points.

Print the maximum possible value of the hedgehog's beauty.

NoteThe picture below corresponds to the first sample. Segments that form the hedgehog are painted red. The tail consists of a sequence of points with numbers 1, 2 and 5. The following segments are spines: (2, 5), (3, 5) and (4, 5). Therefore, the beauty of the hedgehog is equal to 3·3 = 9.

package main

import (
	"bufio"
	"errors"
	"fmt"
	"os"
	"strconv"
	"strings"
)

var (
	numEdges  int
	firstEdge []int
	edgeNxt   []int
	edgeDst   []int
	deg       []int
)

func addEdge(a, b int) {
	e := numEdges
	numEdges++
	edgeNxt[e] = firstEdge[a]
	edgeDst[e] = b
	firstEdge[a] = e
	deg[a]++
}

func main() {
	buf := bufio.NewReader(os.Stdin)
	var n, m int
	fmt.Fscanf(buf, "%d %d\n", &n, &m)
	firstEdge = make([]int, n)
	for i := range firstEdge {
		firstEdge[i] = -1
	}
	edgeNxt = make([]int, 2*m)
	edgeDst = make([]int, 2*m)
	deg = make([]int, n)
	for i := 0; i < m; i++ {
		var a, b int
		fmt.Fscanf(buf, "%d %d\n", &a, &b)
		a--
		b--
		addEdge(a, b)
		addEdge(b, a)
	}
	d := make([]int, n)
	var ans int64
	for i := 0; i < n; i++ {
		d[i] = 1
		for e := firstEdge[i]; e >= 0; e = edgeNxt[e] {
			j := edgeDst[e]
			if j < i && d[i] < d[j]+1 {
				d[i] = d[j] + 1
			}
		}
		var cur int64 = int64(d[i]) * int64(deg[i])
		if ans < cur {
			ans = cur
		}
	}
	fmt.Println(ans)
}

func init() {
	// maybe defer writer.Flush() in main

	lineScanner = bufio.NewScanner(os.Stdin)
	writer = bufio.NewWriter(os.Stdout)

	/*
		inputFile, err := os.Open("a.in")
		if err != nil {
			panic(err)
		}
		outputFile, err := os.Create("a.out")
		if err != nil {
			panic(err)
		}
		lineScanner = bufio.NewScanner(inputFile)
		writer = bufio.NewWriter(outputFile)
	*/

	wordScanner = bufio.NewScanner(strings.NewReader(""))
	wordScanner.Split(bufio.ScanWords)
}

var lineScanner *bufio.Scanner
var wordScanner *bufio.Scanner

var writer *bufio.Writer

func nextLine() (string, error) {
	if !lineScanner.Scan() {
		if err := lineScanner.Err(); err != nil {
			panic(err)
		}
		return "", errors.New("nextLine: EOF reached")
	}
	return lineScanner.Text(), nil
}

func nextWord() string {
	for !wordScanner.Scan() {
		if err := wordScanner.Err(); err != nil {
			panic(err)
		}
		line, err := nextLine()
		if err != nil {
			return ""
		}
		wordScanner = bufio.NewScanner(strings.NewReader(line))
		wordScanner.Split(bufio.ScanWords)
	}
	return wordScanner.Text()
}

func nextInt() int {
	res, err := strconv.Atoi(nextWord())
	if err != nil {
		panic(err)
	}
	return res
}

func nextInt64() int64 {
	res, err := strconv.ParseInt(nextWord(), 10, 64)
	if err != nil {
		panic(err)
	}
	return res
}

func nextFloat64() float64 {
	res, err := strconv.ParseFloat(nextWord(), 64)
	if err != nil {
		panic(err)
	}
	return res
}


You invited $$$n$$$ guests to dinner! You plan to arrange one or more circles of chairs. Each chair is going to be either occupied by one guest, or be empty. You can make any number of circles. Your guests happen to be a little bit shy, so the $$$i$$$-th guest wants to have a least $$$l_i$$$ free chairs to the left of his chair, and at least $$$r_i$$$ free chairs to the right. The "left" and "right" directions are chosen assuming all guests are going to be seated towards the center of the circle. Note that when a guest is the only one in his circle, the $$$l_i$$$ chairs to his left and $$$r_i$$$ chairs to his right may overlap.What is smallest total number of chairs you have to use?

First line contains one integer $$$n$$$  — number of guests, ($$$1 \leqslant n \leqslant 10^5$$$).  Next $$$n$$$ lines contain $$$n$$$ pairs of space-separated integers $$$l_i$$$ and $$$r_i$$$ ($$$0 \leqslant l_i, r_i \leqslant 10^9$$$).

Output a single integer — the smallest number of chairs you have to use.

NoteIn the second sample the only optimal answer is to use two circles: a circle with $$$5$$$ chairs accomodating guests $$$1$$$ and $$$2$$$, and another one with $$$10$$$ chairs accomodationg guests $$$3$$$ and $$$4$$$.In the third sample, you have only one circle with one person. The guest should have at least five free chairs to his left, and at least six free chairs to his right to the next person, which is in this case the guest herself. So, overall number of chairs should be at least 6+1=7.

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
	"sort"
)

// github.com/EndlessCheng/codeforces-go
func CF1060D(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	max := func(a, b int) int {
		if a > b {
			return a
		}
		return b
	}

	var n int
	Fscan(in, &n)
	l := make([]int, n)
	r := make([]int, n)
	for i := range l {
		Fscan(in, &l[i], &r[i])
	}
	sort.Ints(l)
	sort.Ints(r)
	ans := int64(n)
	for i, v := range l {
		ans += int64(max(v, r[i]))
	}
	Fprint(out, ans)
}

func main() { CF1060D(os.Stdin, os.Stdout) }


You are given an undirected graph, consisting of $$$n$$$ vertices and $$$m$$$ edges. The graph does not necessarily connected. Guaranteed, that the graph does not contain multiple edges (more than one edges between a pair of vertices) or loops (edges from a vertex to itself).A cycle in a graph is called a simple, if it contains each own vertex exactly once. So simple cycle doesn't allow to visit a vertex more than once in a cycle.Determine the edges, which belong to exactly on one simple cycle.

The first line contain two integers $$$n$$$ and $$$m$$$ $$$(1 \le n \le 100\,000$$$, $$$0 \le m \le \min(n \cdot (n - 1) / 2, 100\,000))$$$ — the number of vertices and the number of edges. Each of the following $$$m$$$ lines contain two integers $$$u$$$ and $$$v$$$ ($$$1 \le u, v \le n$$$, $$$u \neq v$$$) — the description of the edges.

In the first line print the number of edges, which belong to exactly one simple cycle. In the second line print the indices of edges, which belong to exactly one simple cycle, in increasing order. The edges are numbered from one in the same order as they are given in the input.

package main

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

const (
	HOUSTON = false
)

type caseInput struct {
	n, m uint32
	ac   *EdgeList
}

func readCaseInput(scanner *bufio.Scanner) caseInput {
	n := uint32(readInt(scanner))
	m := uint32(readInt(scanner))

	el := EdgeListNew(n + 1)
	for label := uint32(1); label <= m; label++ {
		source := uint32(readInt(scanner))
		target := uint32(readInt(scanner))
		el.AddEdge(source, target, label)
	}

	return caseInput{n, m, el}
}

type caseOutput struct {
	simpleCycleLabels []uint32
}

func writeCaseOutput(writer *bufio.Writer, out caseOutput) {
	writef(writer, "%d\n", len(out.simpleCycleLabels))
	for _, l := range out.simpleCycleLabels {
		writef(writer, "%d ", l)
	}
}

//noinspection GoBoolExpressions
func solveCase(in caseInput) caseOutput {
	cycleLabelUF := UnionFindNew(in.m + 1) //	which cycles intersect

	dfsLevels := make([]uint32, in.n+1)
	cycleTops := make([]uint32, in.m+1)
	dfsEdges := make([]*Edge, in.n+1)

	vertexQ := make([]*Edge, 0, in.n)
	cycleEdges := make([]*Edge, 0, in.m)
	dfsStart := uint32(1)
	for dfsStart <= in.n {
		if dfsEdges[dfsStart] != nil {
			dfsStart += 1
			continue
		}

		vertexQ = append(vertexQ[:0], &Edge{0, dfsStart, 0, 0, nil})
		cycleEdges = cycleEdges[:0]
		dfsLevels[dfsStart] = 1

		for len(vertexQ) > 0 {
			edgeToSource := vertexQ[len(vertexQ)-1]
			source := edgeToSource.Target
			sourceLevel := dfsLevels[source]
			vertexQ = vertexQ[:len(vertexQ)-1]

			if HOUSTON {
				fmt.Printf("edgesFor %d (%d)\n", source, len(in.ac.EdgesFor(source)))
			}
			for _, e := range in.ac.EdgesFor(source) {

				if e.Target == edgeToSource.Source {
					if HOUSTON {
						fmt.Printf("\tBACKSTOP\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
					}
					continue // same link we used for DFS, but seen from the other side
				}

				if dfsLevels[e.Target] == 0 {
					if HOUSTON {
						fmt.Printf("\tPROPAGATE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
					}
					//	add all new vertexes to spanning tree
					vertexQ = append(vertexQ, e)
					dfsEdges[e.Target] = e
					dfsLevels[e.Target] = sourceLevel + 1
				} else {
					if e.Source < e.Target {
						if HOUSTON {
							fmt.Printf("\tCYCLE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
						}
						//	this edge forms a cycle
						cycleEdges = append(cycleEdges, e)
					} else {
						//	do nothing, we'll see this edge from the other side
						if HOUSTON {
							fmt.Printf("\tCYCLE DUPE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
						}
					}
				}
			}
		}

		if HOUSTON {
			fmt.Printf("dfsLevels = %v\n", dfsLevels)
			fmt.Printf("cycleEdges (%d)\n", len(cycleEdges))
			for _, e := range cycleEdges {
				fmt.Printf("%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
			}
			fmt.Printf("dfsEdges\n")
			for i, e := range dfsEdges {
				if e != nil {
					fmt.Printf("\t%d %d -> %d\t%d\t%d\n", i, e.Source, e.Target, e.Label, e.CycleLabel)
				} else {
					fmt.Printf("\t%d NIL\n", i)
				}
			}
		}

		for _, ce := range cycleEdges {
			cycleLabel := ce.Label
			ce.CycleLabel = cycleLabel
			ce.Reverse.CycleLabel = cycleLabel
			s := ce.Source
			t := ce.Target
			if HOUSTON {
				fmt.Printf(
					"cycleEdge\t%d -> %d\t%d\t%d\n",
					ce.Source, ce.Target, ce.Label, ce.CycleLabel,
				)
			}

			for s != t {
				if dfsLevels[s] >= dfsLevels[t] {
					if HOUSTON {
						fmt.Printf(
							"\tdfsEdges[s=%d at level %d]\t%d -> %d\t%d\t%d\n",
							s, dfsLevels[s], dfsEdges[s].Source, dfsEdges[s].Target, dfsEdges[s].Label, dfsEdges[s].CycleLabel,
						)
					}
					if dfsEdges[s].CycleLabel == cycleLabel {
						panic(fmt.Sprintf("seen same cycle with label %d", cycleLabel))
					} else if dfsEdges[s].CycleLabel > 0 {
						if HOUSTON {
							fmt.Printf("\t\tUNION %d with %d\n", cycleLabel, dfsEdges[s].CycleLabel)
							fmt.Printf("\t\ts <== %d\n", cycleTops[dfsEdges[s].CycleLabel])
						}
						cycleLabelUF.Union(dfsEdges[s].CycleLabel, cycleLabel)
						s = cycleTops[dfsEdges[s].CycleLabel]
					} else {
						if HOUSTON {
							fmt.Printf("\t\tLABEL with %d\n", cycleLabel)
							fmt.Printf("\t\ts <== %d\n", dfsEdges[s].Source)
						}
						dfsEdges[s].CycleLabel = cycleLabel
						dfsEdges[s].Reverse.CycleLabel = cycleLabel
						s = dfsEdges[s].Source
					}
				} else {
					if HOUSTON {
						fmt.Printf(
							"\tdfsEdges[t=%d at level %d]\t%d -> %d\t%d\t%d\n",
							t, dfsLevels[t], dfsEdges[t].Source, dfsEdges[t].Target, dfsEdges[t].Label, dfsEdges[t].CycleLabel,
						)
					}
					if dfsEdges[t].CycleLabel == cycleLabel {
						panic(fmt.Sprintf("seen same cycle with label %d", cycleLabel))
					} else if dfsEdges[t].CycleLabel > 0 {
						if HOUSTON {
							fmt.Printf("\t\tUNION %d with %d\n", cycleLabel, dfsEdges[t].CycleLabel)
							fmt.Printf("\t\tt = %d\n", cycleTops[dfsEdges[t].CycleLabel])
						}
						cycleLabelUF.Union(dfsEdges[t].CycleLabel, cycleLabel)
						t = cycleTops[dfsEdges[t].CycleLabel]
					} else {
						if HOUSTON {
							fmt.Printf("\t\tLABEL with %d\n", cycleLabel)
							fmt.Printf("\t\tt = %d\n", dfsEdges[t].Source)
						}
						dfsEdges[t].CycleLabel = cycleLabel
						dfsEdges[t].Reverse.CycleLabel = cycleLabel
						t = dfsEdges[t].Source
					}
				}
			}
			cycleTops[cycleLabel] = s
		}

		dfsStart += 1
	}

	simpleCycleLabels := make([]uint32, 0, in.m)

	if HOUSTON {
		fmt.Printf("Final edge filter\n")
	}
	for _, e := range in.ac.Added {
		if HOUSTON {
			fmt.Printf(
				"\t%d -> %d\t%d\t%d\n",
				e.Source, e.Target, e.Label, e.CycleLabel,
			)
		}

		if e.CycleLabel > 0 {
			ufSize := cycleLabelUF.Size(e.CycleLabel)
			if HOUSTON {
				fmt.Printf(
					"\t\tnumber of intersecting cycles: %d\n",
					ufSize,
				)
			}
			if ufSize == 1 {
				simpleCycleLabels = append(simpleCycleLabels, e.Label)
			}
		}
	}

	// sort.Sort(Uint32Sort(simpleCycleLabels))

	return caseOutput{simpleCycleLabels}
}

//type Uint32Sort []uint32
//
//func (s Uint32Sort) Len() int           { return len(s) }
//func (s Uint32Sort) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
//func (s Uint32Sort) Less(i, j int) bool { return s[i] < s[j] }

func main() {
	var scanner *bufio.Scanner
	if len(os.Args) > 1 {
		reader, err := os.Open(os.Args[1])
		if err != nil {
			panic(err)
		}
		defer reader.Close()
		scanner = bufio.NewScanner(reader)
	} else {
		scanner = bufio.NewScanner(os.Stdin)
	}
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 0, 1024*1024), 1024*1024)

	var writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	writeCaseOutput(writer, solveCase(readCaseInput(scanner)))
}

func readInt64(sc *bufio.Scanner) int64 {
	if !sc.Scan() {
		panic("failed to scan next token")
	}

	res, err := strconv.ParseInt(sc.Text(), 10, 64)
	if err != nil {
		panic(err)
	}
	return res
}

func readInt(sc *bufio.Scanner) int {
	return int(readInt64(sc))
}

func writef(writer *bufio.Writer, formatStr string, values ...interface{}) {
	out := fmt.Sprintf(formatStr, values...)
	_, err := writer.WriteString(out)
	if err != nil {
		panic(err)
	}
}

type Edge struct {
	Source, Target uint32
	Label          uint32
	CycleLabel     uint32
	Reverse        *Edge
}

type EdgeList struct {
	Added []*Edge
	Edges [][]*Edge
}

func EdgeListNew(
	numNodes uint32,
) *EdgeList {
	edges := make([][]*Edge, numNodes+1, numNodes+1)
	added := make([]*Edge, 0, numNodes+1)
	for i := range edges {
		edges[i] = make([]*Edge, 0, 32)
	}
	return &EdgeList{
		added,
		edges,
	}
}

func (el *EdgeList) AddEdge(source, target uint32, label uint32) {
	added := &Edge{source, target, label, 0, nil}
	reverse := &Edge{target, source, label, 0, nil}

	added.Reverse = reverse
	reverse.Reverse = added

	el.Added = append(el.Added, added)
	el.Edges[source] = append(el.Edges[source], added)
	el.Edges[target] = append(el.Edges[target], reverse)
}

func (el *EdgeList) EdgesFor(source uint32) []*Edge {
	return el.Edges[source]
}

type UnionFind struct {
	parent []uint32
	size   []uint32
	count  uint32
}

func UnionFindNew(count uint32) *UnionFind {
	parent := make([]uint32, count, count)
	size := make([]uint32, count, count)
	lim := uint32(count)
	for i := uint32(0); i < lim; i++ {
		parent[i], size[i] = i, 1
	}
	return &UnionFind{parent, size, lim}
}

func (ufp *UnionFind) Reset() {
	lim := uint32(len(ufp.parent))
	for i := uint32(0); i < lim; i++ {
		ufp.parent[i], ufp.size[i] = i, 1
	}
	ufp.count = lim
}

func (ufp *UnionFind) validate(p uint32) {
	n := uint32(len(ufp.parent))
	if p >= n {
		panic(fmt.Sprintf("index %d is not between 0 and %d", p, n-1))
	}
}

func (ufp *UnionFind) Count() uint32 {
	return ufp.count
}

func (ufp *UnionFind) Find(p uint32) uint32 {
	ufp.validate(p)

	root := p
	for root != ufp.parent[root] {
		root = ufp.parent[root]
	}
	for p != root {
		newp := ufp.parent[p]
		ufp.parent[p] = root
		p = newp
	}

	return root
}

func (ufp *UnionFind) Size(p uint32) uint32 {
	return ufp.size[ufp.Find(p)]
}

func (ufp *UnionFind) Connected(p, q uint32) bool {
	return ufp.Find(p) == ufp.Find(q)
}

func (ufp *UnionFind) Union(p, q uint32) {
	rootP := ufp.Find(p)
	rootQ := ufp.Find(q)

	if rootP == rootQ {
		return
	}

	if ufp.size[rootP] < ufp.size[rootQ] {
		ufp.parent[rootP] = rootQ
		ufp.size[rootQ] += ufp.size[rootP]
	} else {
		ufp.parent[rootQ] = rootP
		ufp.size[rootP] += ufp.size[rootQ]
	}

	ufp.count -= 1
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF962F(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	min := func(a, b int) int {
		if a < b {
			return a
		}
		return b
	}
	type edge struct{ v, w, eid int }
	type nei struct{ to, eid int }

	var n, m, v, w int
	Fscan(in, &n, &m)
	g := make([][]nei, n)
	for i := 1; i <= m; i++ {
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], nei{w, i})
		g[w] = append(g[w], nei{v, i})
	}

	comps := [][2][]int{}
	bccIDs := make([]int, n)
	idCnt := 0
	isCut := make([]bool, n)

	dfn := make([]int, n)
	dfsClock := 0
	stack := []edge{}
	var f func(v, fa int) int
	f = func(v, fa int) int {
		dfsClock++
		dfn[v] = dfsClock
		lowV := dfsClock
		childCnt := 0
		for _, ne := range g[v] {
			w := ne.to
			e := edge{v, w, ne.eid}
			if dfn[w] == 0 {
				stack = append(stack, e)
				childCnt++
				lowW := f(w, v)
				if lowW >= dfn[v] {
					isCut[v] = true
					idCnt++
					comp := []int{}
					eids := []int{}
					for {
						e, stack = stack[len(stack)-1], stack[:len(stack)-1]
						if bccIDs[e.v] != idCnt {
							bccIDs[e.v] = idCnt
							comp = append(comp, e.v)
						}
						if bccIDs[e.w] != idCnt {
							bccIDs[e.w] = idCnt
							comp = append(comp, e.w)
						}
						eids = append(eids, e.eid)
						if e.v == v && e.w == w {
							break
						}
					}
					comps = append(comps, [2][]int{comp, eids})
				}
				lowV = min(lowV, lowW)
			} else if w != fa && dfn[w] < dfn[v] {
				stack = append(stack, e)
				lowV = min(lowV, dfn[w])
			}
		}
		if fa == -1 && childCnt == 1 {
			isCut[v] = false
		}
		return lowV
	}
	for v, timestamp := range dfn {
		if timestamp == 0 && len(g[v]) > 0 {
			f(v, -1)
		}
	}

	ok := make([]bool, m+1)
	for _, p := range comps {
		if eids := p[1]; len(eids) == len(p[0]) {
			for _, eid := range eids {
				ok[eid] = true
			}
		}
	}
	ans := []interface{}{}
	for i, b := range ok {
		if b {
			ans = append(ans, i)
		}
	}
	Fprintln(out, len(ans))
	Fprint(out, ans...)
}

func main() { CF962F(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF962F(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	min := func(a, b int) int {
		if a < b {
			return a
		}
		return b
	}
	type edge struct{ v, w, eid int }
	type nei struct{ to, eid int }

	var n, m, v, w int
	Fscan(in, &n, &m)
	g := make([][]nei, n)
	for i := 1; i <= m; i++ {
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], nei{w, i})
		g[w] = append(g[w], nei{v, i})
	}

	ok := make([]bool, m+1)
	bccIDs := make([]int, n)
	idCnt := 0
	dfn := make([]int, n)
	dfsClock := 0
	stack := []edge{}
	var f func(v, fa int) int
	f = func(v, fa int) int {
		dfsClock++
		dfn[v] = dfsClock
		lowV := dfsClock
		for _, ne := range g[v] {
			w := ne.to
			e := edge{v, w, ne.eid}
			if dfn[w] == 0 {
				stack = append(stack, e)
				lowW := f(w, v)
				if lowW >= dfn[v] {
					idCnt++
					comp := []int{}
					eids := []int{}
					for {
						e, stack = stack[len(stack)-1], stack[:len(stack)-1]
						if bccIDs[e.v] != idCnt {
							bccIDs[e.v] = idCnt
							comp = append(comp, e.v)
						}
						if bccIDs[e.w] != idCnt {
							bccIDs[e.w] = idCnt
							comp = append(comp, e.w)
						}
						eids = append(eids, e.eid)
						if e.v == v && e.w == w {
							break
						}
					}
					if len(comp) == len(eids) {
						for _, eid := range eids {
							ok[eid] = true
						}
					}
				}
				lowV = min(lowV, lowW)
			} else if w != fa && dfn[w] < dfn[v] {
				stack = append(stack, e)
				lowV = min(lowV, dfn[w])
			}
		}
		return lowV
	}
	for v, ts := range dfn {
		if ts == 0 && len(g[v]) > 0 {
			f(v, -1)
		}
	}

	ans := []interface{}{}
	for i, b := range ok {
		if b {
			ans = append(ans, i)
		}
	}
	Fprintln(out, len(ans))
	Fprint(out, ans...)
}

func main() { CF962F(os.Stdin, os.Stdout) }

package main

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

const (
	HOUSTON = false
)

type caseInput struct {
	n, m uint32
	ac   *EdgeList
}

func readCaseInput(scanner *bufio.Scanner) caseInput {
	n := uint32(readInt(scanner))
	m := uint32(readInt(scanner))

	el := EdgeListNew(n + 1)
	for label := uint32(1); label <= m; label++ {
		source := uint32(readInt(scanner))
		target := uint32(readInt(scanner))
		el.AddEdge(source, target, label)
	}

	return caseInput{n, m, el}
}

type caseOutput struct {
	simpleCycleLabels []uint32
}

func writeCaseOutput(writer *bufio.Writer, out caseOutput) {
	writef(writer, "%d\n", len(out.simpleCycleLabels))
	for _, l := range out.simpleCycleLabels {
		writef(writer, "%d ", l)
	}
}

//noinspection GoBoolExpressions
func solveCase(in caseInput) caseOutput {
	cycleLabelUF := UnionFindNew(in.m + 1) //	which cycles intersect

	dfsLevels := make([]uint32, in.n+1)
	dfsEdges := make([]*Edge, in.n+1)

	vertexQ := make([]*Edge, 0, in.n)
	cycleEdges := make([]*Edge, 0, in.m)
	dfsStart := uint32(1)
	for dfsStart <= in.n {
		if dfsEdges[dfsStart] != nil {
			dfsStart += 1
			continue
		}

		vertexQ = append(vertexQ[:0], &Edge{0, dfsStart, 0, 0, nil})
		cycleEdges = cycleEdges[:0]
		dfsLevels[dfsStart] = 1

		for len(vertexQ) > 0 {
			edgeToSource := vertexQ[len(vertexQ)-1]
			source := edgeToSource.Target
			sourceLevel := dfsLevels[source]
			vertexQ = vertexQ[:len(vertexQ)-1]

			if HOUSTON {
				fmt.Printf("edgesFor %d (%d)\n", source, len(in.ac.EdgesFor(source)))
			}
			for _, e := range in.ac.EdgesFor(source) {

				if e.Target == edgeToSource.Source {
					if HOUSTON {
						fmt.Printf("\tBACKSTOP\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
					}
					continue // same link we used for DFS, but seen from the other side
				}

				if dfsLevels[e.Target] == 0 {
					if HOUSTON {
						fmt.Printf("\tPROPAGATE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
					}
					//	add all new vertexes to spanning tree
					vertexQ = append(vertexQ, e)
					dfsEdges[e.Target] = e
					dfsLevels[e.Target] = sourceLevel + 1
				} else {
					if e.Source < e.Target {
						if HOUSTON {
							fmt.Printf("\tCYCLE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
						}
						//	this edge forms a cycle
						cycleEdges = append(cycleEdges, e)
					} else {
						//	do nothing, we'll see this edge from the other side
						if HOUSTON {
							fmt.Printf("\tCYCLE DUPE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
						}
					}
				}
			}
		}

		if HOUSTON {
			fmt.Printf("dfsLevels = %v\n", dfsLevels)
			fmt.Printf("cycleEdges (%d)\n", len(cycleEdges))
			for _, e := range cycleEdges {
				fmt.Printf("%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
			}
			fmt.Printf("dfsEdges\n")
			for i, e := range dfsEdges {
				if e != nil {
					fmt.Printf("\t%d %d -> %d\t%d\t%d\n", i, e.Source, e.Target, e.Label, e.CycleLabel)
				} else {
					fmt.Printf("\t%d NIL\n", i)
				}
			}
		}

		for _, ce := range cycleEdges {
			cycleLabel := ce.Label
			ce.CycleLabel = cycleLabel
			ce.Reverse.CycleLabel = cycleLabel
			s := ce.Source
			t := ce.Target
			if HOUSTON {
				fmt.Printf(
					"cycleEdge\t%d -> %d\t%d\t%d\n",
					ce.Source, ce.Target, ce.Label, ce.CycleLabel,
				)
			}

			sPathUnique := true
			tPathUnique := true
			for s != t && (sPathUnique || tPathUnique) {
				if dfsLevels[s] >= dfsLevels[t] {
					if HOUSTON {
						fmt.Printf(
							"\tdfsEdges[s=%d at level %d]\t%d -> %d\t%d\t%d\n",
							s, dfsLevels[s], dfsEdges[s].Source, dfsEdges[s].Target, dfsEdges[s].Label, dfsEdges[s].CycleLabel,
						)
					}
					if dfsEdges[s].CycleLabel > 0 {
						if HOUSTON {
							fmt.Printf("\t\tUNION %d with %d\n", cycleLabel, dfsEdges[s].CycleLabel)
						}
						cycleLabelUF.Union(dfsEdges[s].CycleLabel, cycleLabel)
						sPathUnique = false;
					} else {
						if HOUSTON {
							fmt.Printf("\t\tLABEL with %d\n", cycleLabel)
						}
						dfsEdges[s].CycleLabel = cycleLabel
						dfsEdges[s].Reverse.CycleLabel = cycleLabel
					}
					if HOUSTON {
						fmt.Printf("\t\ts <== %d\n", dfsEdges[s].Source)
					}
					s = dfsEdges[s].Source
				} else {
					if HOUSTON {
						fmt.Printf(
							"\tdfsEdges[t=%d at level %d]\t%d -> %d\t%d\t%d\n",
							t, dfsLevels[t], dfsEdges[t].Source, dfsEdges[t].Target, dfsEdges[t].Label, dfsEdges[t].CycleLabel,
						)
					}
					if dfsEdges[t].CycleLabel > 0 {
						if HOUSTON {
							fmt.Printf("\t\tUNION %d with %d\n", cycleLabel, dfsEdges[t].CycleLabel)
						}
						cycleLabelUF.Union(dfsEdges[t].CycleLabel, cycleLabel)
						tPathUnique = false
					} else {
						if HOUSTON {
							fmt.Printf("\t\tLABEL with %d\n", cycleLabel)
						}
						dfsEdges[t].CycleLabel = cycleLabel
						dfsEdges[t].Reverse.CycleLabel = cycleLabel
					}
					if HOUSTON {
						fmt.Printf("\t\tt = %d\n", dfsEdges[t].Source)
					}
					t = dfsEdges[t].Source
				}
			}
		}

		dfsStart += 1
	}

	simpleCycleLabels := make([]uint32, 0, in.m)

	if HOUSTON {
		fmt.Printf("Final edge filter\n")
	}
	for _, e := range in.ac.Added {
		if HOUSTON {
			fmt.Printf(
				"\t%d -> %d\t%d\t%d\n",
				e.Source, e.Target, e.Label, e.CycleLabel,
			)
		}

		if e.CycleLabel > 0 {
			ufSize := cycleLabelUF.Size(e.CycleLabel)
			if HOUSTON {
				fmt.Printf(
					"\t\tnumber of intersecting cycles: %d\n",
					ufSize,
				)
			}
			if ufSize == 1 {
				simpleCycleLabels = append(simpleCycleLabels, e.Label)
			}
		}
	}

	// sort.Sort(Uint32Sort(simpleCycleLabels))

	return caseOutput{simpleCycleLabels}
}

//type Uint32Sort []uint32
//
//func (s Uint32Sort) Len() int           { return len(s) }
//func (s Uint32Sort) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
//func (s Uint32Sort) Less(i, j int) bool { return s[i] < s[j] }

func main() {
	var scanner *bufio.Scanner
	if len(os.Args) > 1 {
		reader, err := os.Open(os.Args[1])
		if err != nil {
			panic(err)
		}
		defer reader.Close()
		scanner = bufio.NewScanner(reader)
	} else {
		scanner = bufio.NewScanner(os.Stdin)
	}
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 0, 1024*1024), 1024*1024)

	var writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	writeCaseOutput(writer, solveCase(readCaseInput(scanner)))
}

func readInt64(sc *bufio.Scanner) int64 {
	if !sc.Scan() {
		panic("failed to scan next token")
	}

	res, err := strconv.ParseInt(sc.Text(), 10, 64)
	if err != nil {
		panic(err)
	}
	return res
}

func readInt(sc *bufio.Scanner) int {
	return int(readInt64(sc))
}

func writef(writer *bufio.Writer, formatStr string, values ...interface{}) {
	out := fmt.Sprintf(formatStr, values...)
	_, err := writer.WriteString(out)
	if err != nil {
		panic(err)
	}
}

type Edge struct {
	Source, Target uint32
	Label          uint32
	CycleLabel     uint32
	Reverse        *Edge
}

type EdgeList struct {
	Added []*Edge
	Edges [][]*Edge
}

func EdgeListNew(
	numNodes uint32,
) *EdgeList {
	edges := make([][]*Edge, numNodes+1, numNodes+1)
	added := make([]*Edge, 0, numNodes+1)
	for i := range edges {
		edges[i] = make([]*Edge, 0, 32)
	}
	return &EdgeList{
		added,
		edges,
	}
}

func (el *EdgeList) AddEdge(source, target uint32, label uint32) {
	added := &Edge{source, target, label, 0, nil}
	reverse := &Edge{target, source, label, 0, nil}

	added.Reverse = reverse
	reverse.Reverse = added

	el.Added = append(el.Added, added)
	el.Edges[source] = append(el.Edges[source], added)
	el.Edges[target] = append(el.Edges[target], reverse)
}

func (el *EdgeList) EdgesFor(source uint32) []*Edge {
	return el.Edges[source]
}

type UnionFind struct {
	parent []uint32
	size   []uint32
	count  uint32
}

func UnionFindNew(count uint32) *UnionFind {
	parent := make([]uint32, count, count)
	size := make([]uint32, count, count)
	lim := uint32(count)
	for i := uint32(0); i < lim; i++ {
		parent[i], size[i] = i, 1
	}
	return &UnionFind{parent, size, lim}
}

func (ufp *UnionFind) Reset() {
	lim := uint32(len(ufp.parent))
	for i := uint32(0); i < lim; i++ {
		ufp.parent[i], ufp.size[i] = i, 1
	}
	ufp.count = lim
}

func (ufp *UnionFind) validate(p uint32) {
	n := uint32(len(ufp.parent))
	if p >= n {
		panic(fmt.Sprintf("index %d is not between 0 and %d", p, n-1))
	}
}

func (ufp *UnionFind) Count() uint32 {
	return ufp.count
}

func (ufp *UnionFind) Find(p uint32) uint32 {
	ufp.validate(p)

	root := p
	for root != ufp.parent[root] {
		root = ufp.parent[root]
	}
	for p != root {
		newp := ufp.parent[p]
		ufp.parent[p] = root
		p = newp
	}

	return root
}

func (ufp *UnionFind) Size(p uint32) uint32 {
	return ufp.size[ufp.Find(p)]
}

func (ufp *UnionFind) Connected(p, q uint32) bool {
	return ufp.Find(p) == ufp.Find(q)
}

func (ufp *UnionFind) Union(p, q uint32) {
	rootP := ufp.Find(p)
	rootQ := ufp.Find(q)

	if rootP == rootQ {
		return
	}

	if ufp.size[rootP] < ufp.size[rootQ] {
		ufp.parent[rootP] = rootQ
		ufp.size[rootQ] += ufp.size[rootP]
	} else {
		ufp.parent[rootQ] = rootP
		ufp.size[rootP] += ufp.size[rootQ]
	}

	ufp.count -= 1
}

package main

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

const (
	HOUSTON = false
)

type caseInput struct {
	n, m uint32
	ac   *EdgeList
}

func readCaseInput(scanner *bufio.Scanner) caseInput {
	n := uint32(readInt(scanner))
	m := uint32(readInt(scanner))

	el := EdgeListNew(n + 1)
	for label := uint32(1); label <= m; label++ {
		source := uint32(readInt(scanner))
		target := uint32(readInt(scanner))
		el.AddEdge(source, target, label)
	}

	return caseInput{n, m, el}
}

type caseOutput struct {
	simpleCycleLabels []uint32
}

func writeCaseOutput(writer *bufio.Writer, out caseOutput) {
	writef(writer, "%d\n", len(out.simpleCycleLabels))
	for _, l := range out.simpleCycleLabels {
		writef(writer, "%d ", l)
	}
}

//noinspection GoBoolExpressions
func solveCase(in caseInput) caseOutput {
	cycleLabelUF := UnionFindNew(in.m + 1) //	which cycles intersect

	dfsLevels := make([]uint32, in.n+1)
	dfsEdges := make([]*Edge, in.n+1)

	vertexQ := make([]*Edge, 0, in.n)
	cycleEdges := make([]*Edge, 0, in.m)
	dfsStart := uint32(1)
	for dfsStart <= in.n {
		if dfsEdges[dfsStart] != nil {
			dfsStart += 1
			continue
		}

		vertexQ = append(vertexQ[:0], &Edge{0, dfsStart, 0, 0, nil})
		cycleEdges = cycleEdges[:0]
		dfsLevels[dfsStart] = 1

		for len(vertexQ) > 0 {
			edgeToSource := vertexQ[len(vertexQ)-1]
			source := edgeToSource.Target
			sourceLevel := dfsLevels[source]
			vertexQ = vertexQ[:len(vertexQ)-1]

			if HOUSTON {
				fmt.Printf("edgesFor %d (%d)\n", source, len(in.ac.EdgesFor(source)))
			}
			for _, e := range in.ac.EdgesFor(source) {

				if e.Target == edgeToSource.Source {
					if HOUSTON {
						fmt.Printf("\tBACKSTOP\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
					}
					continue // same link we used for DFS, but seen from the other side
				}

				if dfsLevels[e.Target] == 0 {
					if HOUSTON {
						fmt.Printf("\tPROPAGATE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
					}
					//	add all new vertexes to spanning tree
					vertexQ = append(vertexQ, e)
					dfsEdges[e.Target] = e
					dfsLevels[e.Target] = sourceLevel + 1
				} else {
					if e.Source < e.Target {
						if HOUSTON {
							fmt.Printf("\tCYCLE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
						}
						//	this edge forms a cycle
						cycleEdges = append(cycleEdges, e)
					} else {
						//	do nothing, we'll see this edge from the other side
						if HOUSTON {
							fmt.Printf("\tCYCLE DUPE\t%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
						}
					}
				}
			}
		}

		if HOUSTON {
			fmt.Printf("dfsLevels = %v\n", dfsLevels)
			fmt.Printf("cycleEdges (%d)\n", len(cycleEdges))
			for _, e := range cycleEdges {
				fmt.Printf("%d -> %d\t%d\t%d\n", e.Source, e.Target, e.Label, e.CycleLabel)
			}
			fmt.Printf("dfsEdges\n")
			for i, e := range dfsEdges {
				if e != nil {
					fmt.Printf("\t%d %d -> %d\t%d\t%d\n", i, e.Source, e.Target, e.Label, e.CycleLabel)
				} else {
					fmt.Printf("\t%d NIL\n", i)
				}
			}
		}

		for _, ce := range cycleEdges {
			cycleLabel := ce.Label
			ce.CycleLabel = cycleLabel
			ce.Reverse.CycleLabel = cycleLabel
			s := ce.Source
			t := ce.Target
			if HOUSTON {
				fmt.Printf(
					"cycleEdge\t%d -> %d\t%d\t%d\n",
					ce.Source, ce.Target, ce.Label, ce.CycleLabel,
				)
			}

			for s != t {
				if dfsLevels[s] >= dfsLevels[t] {
					if HOUSTON {
						fmt.Printf(
							"\tdfsEdges[s=%d at level %d]\t%d -> %d\t%d\t%d\n",
							s, dfsLevels[s], dfsEdges[s].Source, dfsEdges[s].Target, dfsEdges[s].Label, dfsEdges[s].CycleLabel,
						)
					}
					if dfsEdges[s].CycleLabel > 0 {
						if HOUSTON {
							fmt.Printf("\t\tUNION %d with %d\n", cycleLabel, dfsEdges[s].CycleLabel)
						}
						cycleLabelUF.Union(dfsEdges[s].CycleLabel, cycleLabel)
						break;
					} else {
						if HOUSTON {
							fmt.Printf("\t\tLABEL with %d\n", cycleLabel)
						}
						dfsEdges[s].CycleLabel = cycleLabel
						dfsEdges[s].Reverse.CycleLabel = cycleLabel
					}
					if HOUSTON {
						fmt.Printf("\t\ts <== %d\n", dfsEdges[s].Source)
					}
					s = dfsEdges[s].Source
				} else {
					if HOUSTON {
						fmt.Printf(
							"\tdfsEdges[t=%d at level %d]\t%d -> %d\t%d\t%d\n",
							t, dfsLevels[t], dfsEdges[t].Source, dfsEdges[t].Target, dfsEdges[t].Label, dfsEdges[t].CycleLabel,
						)
					}
					if dfsEdges[t].CycleLabel > 0 {
						if HOUSTON {
							fmt.Printf("\t\tUNION %d with %d\n", cycleLabel, dfsEdges[t].CycleLabel)
						}
						cycleLabelUF.Union(dfsEdges[t].CycleLabel, cycleLabel)
						break
					} else {
						if HOUSTON {
							fmt.Printf("\t\tLABEL with %d\n", cycleLabel)
						}
						dfsEdges[t].CycleLabel = cycleLabel
						dfsEdges[t].Reverse.CycleLabel = cycleLabel
					}
					if HOUSTON {
						fmt.Printf("\t\tt = %d\n", dfsEdges[t].Source)
					}
					t = dfsEdges[t].Source
				}
			}
		}

		dfsStart += 1
	}

	simpleCycleLabels := make([]uint32, 0, in.m)

	if HOUSTON {
		fmt.Printf("Final edge filter\n")
	}
	for _, e := range in.ac.Added {
		if HOUSTON {
			fmt.Printf(
				"\t%d -> %d\t%d\t%d\n",
				e.Source, e.Target, e.Label, e.CycleLabel,
			)
		}

		if e.CycleLabel > 0 {
			ufSize := cycleLabelUF.Size(e.CycleLabel)
			if HOUSTON {
				fmt.Printf(
					"\t\tnumber of intersecting cycles: %d\n",
					ufSize,
				)
			}
			if ufSize == 1 {
				simpleCycleLabels = append(simpleCycleLabels, e.Label)
			}
		}
	}

	// sort.Sort(Uint32Sort(simpleCycleLabels))

	return caseOutput{simpleCycleLabels}
}

//type Uint32Sort []uint32
//
//func (s Uint32Sort) Len() int           { return len(s) }
//func (s Uint32Sort) Swap(i, j int)      { s[i], s[j] = s[j], s[i] }
//func (s Uint32Sort) Less(i, j int) bool { return s[i] < s[j] }

func main() {
	var scanner *bufio.Scanner
	if len(os.Args) > 1 {
		reader, err := os.Open(os.Args[1])
		if err != nil {
			panic(err)
		}
		defer reader.Close()
		scanner = bufio.NewScanner(reader)
	} else {
		scanner = bufio.NewScanner(os.Stdin)
	}
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 0, 1024*1024), 1024*1024)

	var writer = bufio.NewWriter(os.Stdout)
	defer writer.Flush()

	writeCaseOutput(writer, solveCase(readCaseInput(scanner)))
}

func readInt64(sc *bufio.Scanner) int64 {
	if !sc.Scan() {
		panic("failed to scan next token")
	}

	res, err := strconv.ParseInt(sc.Text(), 10, 64)
	if err != nil {
		panic(err)
	}
	return res
}

func readInt(sc *bufio.Scanner) int {
	return int(readInt64(sc))
}

func writef(writer *bufio.Writer, formatStr string, values ...interface{}) {
	out := fmt.Sprintf(formatStr, values...)
	_, err := writer.WriteString(out)
	if err != nil {
		panic(err)
	}
}

type Edge struct {
	Source, Target uint32
	Label          uint32
	CycleLabel     uint32
	Reverse        *Edge
}

type EdgeList struct {
	Added []*Edge
	Edges [][]*Edge
}

func EdgeListNew(
	numNodes uint32,
) *EdgeList {
	edges := make([][]*Edge, numNodes+1, numNodes+1)
	added := make([]*Edge, 0, numNodes+1)
	for i := range edges {
		edges[i] = make([]*Edge, 0, 32)
	}
	return &EdgeList{
		added,
		edges,
	}
}

func (el *EdgeList) AddEdge(source, target uint32, label uint32) {
	added := &Edge{source, target, label, 0, nil}
	reverse := &Edge{target, source, label, 0, nil}

	added.Reverse = reverse
	reverse.Reverse = added

	el.Added = append(el.Added, added)
	el.Edges[source] = append(el.Edges[source], added)
	el.Edges[target] = append(el.Edges[target], reverse)
}

func (el *EdgeList) EdgesFor(source uint32) []*Edge {
	return el.Edges[source]
}

type UnionFind struct {
	parent []uint32
	size   []uint32
	count  uint32
}

func UnionFindNew(count uint32) *UnionFind {
	parent := make([]uint32, count, count)
	size := make([]uint32, count, count)
	lim := uint32(count)
	for i := uint32(0); i < lim; i++ {
		parent[i], size[i] = i, 1
	}
	return &UnionFind{parent, size, lim}
}

func (ufp *UnionFind) Reset() {
	lim := uint32(len(ufp.parent))
	for i := uint32(0); i < lim; i++ {
		ufp.parent[i], ufp.size[i] = i, 1
	}
	ufp.count = lim
}

func (ufp *UnionFind) validate(p uint32) {
	n := uint32(len(ufp.parent))
	if p >= n {
		panic(fmt.Sprintf("index %d is not between 0 and %d", p, n-1))
	}
}

func (ufp *UnionFind) Count() uint32 {
	return ufp.count
}

func (ufp *UnionFind) Find(p uint32) uint32 {
	ufp.validate(p)

	root := p
	for root != ufp.parent[root] {
		root = ufp.parent[root]
	}
	for p != root {
		newp := ufp.parent[p]
		ufp.parent[p] = root
		p = newp
	}

	return root
}

func (ufp *UnionFind) Size(p uint32) uint32 {
	return ufp.size[ufp.Find(p)]
}

func (ufp *UnionFind) Connected(p, q uint32) bool {
	return ufp.Find(p) == ufp.Find(q)
}

func (ufp *UnionFind) Union(p, q uint32) {
	rootP := ufp.Find(p)
	rootQ := ufp.Find(q)

	if rootP == rootQ {
		return
	}

	if ufp.size[rootP] < ufp.size[rootQ] {
		ufp.parent[rootP] = rootQ
		ufp.size[rootQ] += ufp.size[rootP]
	} else {
		ufp.parent[rootQ] = rootP
		ufp.size[rootP] += ufp.size[rootQ]
	}

	ufp.count -= 1
}

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF962F(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	min := func(a, b int) int {
		if a < b {
			return a
		}
		return b
	}
	type nei struct{ to, eid int }
	type edge struct{ v, w int }

	var n, m, v, w int
	Fscan(in, &n, &m)
	g := make([][]nei, n)
	for i := 1; i <= m; i++ {
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], nei{w, i})
		g[w] = append(g[w], nei{v, i})
	}

	comps := [][]int{}
	bccIDs := make([]int, n)
	idCnt := 0
	isCut := make([]bool, n)

	dfn := make([]int, n)
	dfsClock := 0
	stack := []edge{}
	var f func(v, fa int) int
	f = func(v, fa int) int {
		dfsClock++
		dfn[v] = dfsClock
		lowV := dfsClock
		childCnt := 0
		for _, ne := range g[v] {
			w := ne.to
			e := edge{v, w}
			if dfn[w] == 0 {
				stack = append(stack, e)
				childCnt++
				lowW := f(w, v)
				if lowW >= dfn[v] {
					isCut[v] = true
					idCnt++
					comp := []int{}
					for {
						e, stack = stack[len(stack)-1], stack[:len(stack)-1]
						if bccIDs[e.v] != idCnt {
							bccIDs[e.v] = idCnt
							comp = append(comp, e.v)
						}
						if bccIDs[e.w] != idCnt {
							bccIDs[e.w] = idCnt
							comp = append(comp, e.w)
						}
						if e.v == v && e.w == w {
							break
						}
					}
					comps = append(comps, comp)
				}
				lowV = min(lowV, lowW)
			} else if w != fa && dfn[w] < dfn[v] {
				stack = append(stack, e)
				lowV = min(lowV, dfn[w])
			}
		}
		if fa == -1 && childCnt == 1 {
			isCut[v] = false
		}
		return lowV
	}
	for v, timestamp := range dfn {
		if timestamp == 0 && len(g[v]) > 0 {
			f(v, -1)
		}
	}

	ok := make([]bool, m+1)
	for _, vs := range comps {
		bad := false
		for _, v := range vs {
			if !isCut[v] && len(g[v]) != 2 {
				bad = true
				break
			}
		}
		if !bad {
			for _, v := range vs {
				if !isCut[v] {
					ok[g[v][0].eid] = true
					ok[g[v][1].eid] = true
				}
			}
		}
	}
	ans := []interface{}{}
	for i, b := range ok {
		if b {
			ans = append(ans, i)
		}
	}
	Fprintln(out, len(ans))
	Fprint(out, ans...)
}

func main() { CF962F(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF962F(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	min := func(a, b int) int {
		if a < b {
			return a
		}
		return b
	}
	type edge struct{ v, w,eid int }
	type nei struct{ to, eid int }

	var n, m, v, w int
	Fscan(in, &n, &m)
	g := make([][]nei, n)
	for i := 1; i <= m; i++ {
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], nei{w,i})
		g[w] = append(g[w], nei{v,i})
	}

	comps := [][2][]int{}
	bccIDs := make([]int, n)
	idCnt := 0
	isCut := make([]bool, n)

	dfn := make([]int, n)
	dfsClock := 0
	stack := []edge{}
	var f func(v, fa int) int
	f = func(v, fa int) int {
		dfsClock++
		dfn[v] = dfsClock
		lowV := dfsClock
		childCnt := 0
		for _, ne := range g[v] {
			w := ne.to
			e := edge{v, w,ne.eid}
			if dfn[w] == 0 {
				stack = append(stack, e)
				childCnt++
				lowW := f(w, v)
				if lowW >= dfn[v] {
					isCut[v] = true
					idCnt++
					comp := []int{}
					eids := []int{}
					for {
						e, stack = stack[len(stack)-1], stack[:len(stack)-1]
						if bccIDs[e.v] != idCnt {
							bccIDs[e.v] = idCnt
							comp = append(comp, e.v)
						}
						if bccIDs[e.w] != idCnt {
							bccIDs[e.w] = idCnt
							comp = append(comp, e.w)
						}
						eids = append(eids,e.eid )
						if e.v == v && e.w == w {
							break
						}
					}
					comps = append(comps, [2][]int{comp,eids})
				}
				lowV = min(lowV, lowW)
			} else if w != fa && dfn[w] < dfn[v] {
				stack = append(stack, e)
				lowV = min(lowV, dfn[w])
			}
		}
		if fa == -1 && childCnt == 1 {
			isCut[v] = false
		}
		return lowV
	}
	for v, timestamp := range dfn {
		if timestamp == 0 && len(g[v]) > 0 {
			f(v, -1)
		}
	}

	ok := make([]bool, m+1)
	for _, p := range comps {
		vs, eids := p[0],p[1]
		if len(vs) < 3 {
			continue
		}
		bad := false
		for _, v := range vs {
			if !isCut[v] && len(g[v]) != 2 {
				bad = true
				break
			}
		}
		if !bad {
			for _, eid := range eids {
				ok[eid]=true
			}
		}
	}
	ans := []interface{}{}
	for i, b := range ok {
		if b {
			ans = append(ans, i)
		}
	}
	Fprintln(out, len(ans))
	Fprint(out, ans...)
}

func main() { CF962F(os.Stdin, os.Stdout) }

package main

import (
	"bufio"
	. "fmt"
	"io"
	"os"
)

// github.com/EndlessCheng/codeforces-go
func CF962F(_r io.Reader, _w io.Writer) {
	in := bufio.NewReader(_r)
	out := bufio.NewWriter(_w)
	defer out.Flush()
	min := func(a, b int) int {
		if a < b {
			return a
		}
		return b
	}
	type edge struct{ v, w int }

	var n, m, v, w int
	Fscan(in, &n, &m)
	g := make([][]int, n)
	idMap := map[[2]int]int{}
	for i := 1; i <= m; i++ {
		Fscan(in, &v, &w)
		v--
		w--
		g[v] = append(g[v], w)
		g[w] = append(g[w], v)
		if v > w {
			v, w = w, v
		}
		idMap[[2]int{v, w}] = i
	}

	comps := [][]int{}
	bccIDs := make([]int, n)
	idCnt := 0
	isCut := make([]bool, n)

	dfn := make([]int, n)
	dfsClock := 0
	stack := []edge{}
	var f func(v, fa int) int
	f = func(v, fa int) int {
		dfsClock++
		dfn[v] = dfsClock
		lowV := dfsClock
		childCnt := 0
		for _, w := range g[v] {
			e := edge{v, w}
			if dfn[w] == 0 {
				stack = append(stack, e)
				childCnt++
				lowW := f(w, v)
				if lowW >= dfn[v] {
					isCut[v] = true
					idCnt++
					comp := []int{}
					for {
						e, stack = stack[len(stack)-1], stack[:len(stack)-1]
						if bccIDs[e.v] != idCnt {
							bccIDs[e.v] = idCnt
							comp = append(comp, e.v)
						}
						if bccIDs[e.w] != idCnt {
							bccIDs[e.w] = idCnt
							comp = append(comp, e.w)
						}
						if e.v == v && e.w == w {
							break
						}
					}
					comps = append(comps, comp)
				}
				lowV = min(lowV, lowW)
			} else if w != fa && dfn[w] < dfn[v] {
				stack = append(stack, e)
				lowV = min(lowV, dfn[w])
			}
		}
		if fa == -1 && childCnt == 1 {
			isCut[v] = false
		}
		return lowV
	}
	for v, timestamp := range dfn {
		if timestamp == 0 && len(g[v]) > 0 {
			f(v, -1)
		}
	}

	ok := make([]bool, m+1)
	for _, vs := range comps {
		if len(vs) < 3 {
			continue
		}
		bad := false
		for _, v := range vs {
			if !isCut[v] && len(g[v]) != 2 {
				bad = true
				break
			}
		}
		if !bad {
			vs = append(vs, vs[0])
			for i := 0; i < len(vs)-1; i++ {
				v, w := vs[i], vs[i+1]
				if v > w {
					v, w = w, v
				}
				ok[idMap[[2]int{v, w}]] = true
			}
		}
	}
	ans := []interface{}{}
	for i, b := range ok {
		if b {
			ans = append(ans, i)
		}
	}
	Fprintln(out, len(ans))
	Fprint(out, ans...)
}

func main() { CF962F(os.Stdin, os.Stdout) }


A tree is a connected undirected graph without cycles. Note that in this problem, we are talking about not rooted trees.You are given four positive integers $$$n, d_{12}, d_{23}$$$ and $$$d_{31}$$$. Construct a tree such that:  it contains $$$n$$$ vertices numbered from $$$1$$$ to $$$n$$$,  the distance (length of the shortest path) from vertex $$$1$$$ to vertex $$$2$$$ is $$$d_{12}$$$,  distance from vertex $$$2$$$ to vertex $$$3$$$ is $$$d_{23}$$$,  the distance from vertex $$$3$$$ to vertex $$$1$$$ is $$$d_{31}$$$. Output any tree that satisfies all the requirements above, or determine that no such tree exists.

The first line of the input contains an integer $$$t$$$ ($$$1 \le t \le 10^4$$$) —the number of test cases in the test. This is followed by $$$t$$$ test cases, each written on a separate line. Each test case consists of four positive integers $$$n, d_{12}, d_{23}$$$ and $$$d_{31}$$$ ($$$3 \le n \le 2\cdot10^5; 1 \le d_{12}, d_{23}, d_{31} \le n-1$$$). It is guaranteed that the sum of $$$n$$$ values for all test cases does not exceed $$$2\cdot10^5$$$.

For each test case, print YES if the suitable tree exists, and NO otherwise.  If the answer is positive, print another $$$n-1$$$ line each containing a description of an edge of the tree — a pair of positive integers $$$x_i, y_i$$$, which means that the $$$i$$$th edge connects vertices $$$x_i$$$ and $$$y_i$$$.  The edges and vertices of the edges can be printed in any order. If there are several suitable trees, output any of them.

package main

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

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d12, d23, d31, l, cnt, rcd int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d12, &d23, &d31)
		if d12+d23 < d31 || (d12+d23-d31)%2 != 0 {
			fmt.Fprintln(out, "NO")
			continue
		}
		l, cnt = (d12+d23-d31)/2, 4
		if d31+1+l > n {
			fmt.Fprintln(out, "NO")
			continue
		}
		if l == 0 {
			fmt.Fprintln(out, "YES")
			for last, i := 1, 1; i <= d12; i++ {
				if i == d12 {
					fmt.Fprintln(out, last, 2)
				} else {
					fmt.Fprintln(out, last, cnt)
					last, cnt = cnt, cnt+1
				}
			}
			for last, i := 2, 1; i <= d23; i++ {
				if i == d23 {
					fmt.Fprintln(out, last, 3)
				} else {
					fmt.Fprintln(out, last, cnt)
					last, cnt = cnt, cnt+1
				}
			}
			for cnt <= n {
				fmt.Fprintln(out, 1, cnt)
				cnt++
			}
		} else {
			d1m := d12 - l
			if d1m < 0 || d1m > d31 {
				fmt.Fprintln(out, "NO")
				continue
			} else if d1m == 0 {
				rcd = 1
			} else if d1m == d31 {
				rcd = 3
			} else {
				rcd = 4 + d1m - 1
			}
			fmt.Fprintln(out, "YES")
			for last, i := 1, 1; i <= d31; i++ {
				if i == d31 {
					fmt.Fprintln(out, last, 3)
				} else {
					fmt.Fprintln(out, last, cnt)
					last, cnt = cnt, cnt+1
				}
			}
			for last, i := rcd, 1; i <= l; i++ {
				if i == l {
					fmt.Fprintln(out, last, 2)
				} else {
					fmt.Fprintln(out, last, cnt)
					last, cnt = cnt, cnt+1
				}
			}
			for cnt <= n {
				fmt.Fprintln(out, 1, cnt)
				cnt++
			}
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0 {
			fmt.Fprintln(out, "NO")
			continue
		}

		tt /= 2

		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0 {
			fmt.Fprintln(out, "NO")
			continue
		}

		nodes := d1 + d2 + d3 + 1

		if nodes > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5

		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		gogo := func(first int, cur int, d int) {
			for ;d>1;d--{
				fmt.Fprintln(out, cur, id)
				cur = id
				id++
			}
			if d > 0 {
				fmt.Fprintln(out, cur, first)
			}
		}

		gogo(1, root, d1)
		gogo(2, root, d2)
		gogo(3, root, d3)

		cur := root
		for ; id <= n; id++{
			fmt.Fprintln(out, cur, id)
			cur = id
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0 {
			fmt.Fprintln(out, "NO")
			continue
		}

		tt /= 2

		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0 {
			fmt.Fprintln(out, "NO")
			continue
		}

		nodes := d1 + d2 + d3 + 1

		if nodes > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5

		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		gogo := func(first int, cur int, d int, id *int) {
			for ;d>1;d--{
				fmt.Fprintln(out, cur, *id)
				cur = *id
				*id++
			}
			if d > 0 {
				fmt.Fprintln(out, cur, first)
			}
		}

		gogo(1, root, d1, &id)
		gogo(2, root, d2, &id)
		gogo(3, root, d3, &id)

		cur := root
		for ; id <= n; id++{
			fmt.Fprintln(out, cur, id)
			cur = id
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0 {
			fmt.Fprintln(out, "NO")
			continue
		}

		tt /= 2

		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0 {
			fmt.Fprintln(out, "NO")
			continue
		}

		nodes := d1 + d2 + d3 + 1

		if nodes > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5

		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		cur := root
		for ;d1>1;d1--{
			fmt.Fprintln(out, cur, id)
			cur = id
			id++
		}
		if d1 > 0 {
			fmt.Fprintln(out, cur,  1)
		}

		cur = root
		for ;d2>1;d2--{
			fmt.Fprintln(out,cur, id)
			cur = id
			id++
		}
		if d2 > 0{
			fmt.Fprintln(out, cur, 2)
		}

		cur = root
		for ;d3>1;d3--{
			fmt.Fprintln(out, cur, id)
			cur = id
			id++
		}
		if d3 > 0{
			fmt.Fprintln(out, cur, 3)
		}

		cur = root
		for ; id <= n; id++{
			fmt.Fprintln(out, cur, id)
			cur = id
		}
	}
}

package main

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

var in = bufio.NewReader(os.Stdin)
var out = bufio.NewWriter(os.Stdout)
var qq = 0
var cnt = 0

func qwq() {
	cnt++
	var n, d12, d23, d31 int
	// fmt.Fscanf(in, "%d %d %d %d", &n, &d12, &d23, &d31)
	fmt.Fscanln(in, &n, &d12, &d23, &d31)
	// fmt.Fprintln(out, n, d12, d23, d31)
	res := [][2]int{}

	d := (d12 + d31 - d23) / 2
	id := 4
	conn := func(v1, v2, v3, d1, d2 int) {
		la := v1
		for i := 1; i < d1; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		res = append(res, [2]int{la, v2})
		la = v2
		for i := 1; i < d2; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		res = append(res, [2]int{la, v3})
		for id <= n {
			res = append(res, [2]int{1, id})
			id++
		}
	}

	if d12+d23 == d31 {
		conn(1, 2, 3, d12, d23)
	} else if d31+d23 == d12 {
		conn(1, 3, 2, d31, d23)
	} else {
		if (d12+d31 < d23) || (d12+d31-d23)%2 != 0 || (d >= d12 || d >= d31) {
			fmt.Fprintln(out, "NO")
			return
		}
		la := 1
		for i := 0; i < d; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		l2 := la
		for i := 1; i < d12-d; i++ {
			res = append(res, [2]int{l2, id})
			l2 = id
			id++
		}
		res = append(res, [2]int{l2, 2})
		l3 := la
		for i := 1; i < d31-d; i++ {
			res = append(res, [2]int{l3, id})
			l3 = id
			id++
		}
		res = append(res, [2]int{l3, 3})
		for id <= n {
			res = append(res, [2]int{1, id})
			id++
		}
	}
	if qq == -1 {
		if cnt == 103 {
			fmt.Fprintln(out, n, d12, d23, d31)
			for _, v := range res {
				fmt.Fprintln(out, v[0], v[1])
			}
		}
	} else {
		if id == n+1 {
			fmt.Fprintln(out, "YES")
			for _, v := range res {
				fmt.Fprintln(out, v[0], v[1])
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}
func main() {
	defer out.Flush()
	q := 1
	fmt.Fscanln(in, &q)
	qq = q
	for ; q > 0; q-- {
		qwq()
	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

func solve(n, d12, d23, d31 int) {
	var mind, maxd int
	b := false
	i := minInt(d12, d31)

	if i == d12 {
		mind = 2
		maxd = 3
	} else {
		mind = 3
		maxd = 2
	}

	for ; i >= 0; i-- {
		if (d12-i)+(d31-i) == d23 {
			b = true
			break
		}
	}

	if !b {
		fmt.Println("No")
		return
	}
	extra := n - ((i + 1) + (d12 - i) + (d31 - i))

	if extra < 0 {
		fmt.Println("No")
		return
	}

	fmt.Println("Yes")

	src := 1
	if i == minInt(d12, d31) {
		src = pathAToB(1, mind, 3, i)
		src = pathAToB(mind, maxd, src-1, maxInt(d12, d31)-i)
	}
	if 0 < i && i < minInt(d12, d31) {
		src = pathAToB(1, 4, 4, i)
		src = pathAToB(4, 2, src-1, d12-i)
		src = pathAToB(4, 3, src-1, d31-i)
	}

	if i == 0 {
		src = pathAToB(1, 2, 3, d12)
		src = pathAToB(1, 3, src-1, d31)
	}
	for ii := n - extra + 1; ii <= n; ii++ {
		fmt.Println(1, ii)
	}

}
func pathAToB(src, dist, cnt, length int) int {
	a := src
	j := 0
	for j = 1; j < length; j++ {
		fmt.Println(a, cnt+j)
		a = cnt + j
	}
	if length > 0 {
		fmt.Println(a, dist)
	}
	return cnt + j
}
func minInt(a, b int) int {
	if a > b {
		return b
	}
	return a
}
func maxInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	reader := bufio.NewReaderSize(os.Stdin, 16*1024*1024)

	qTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
	checkError(err)
	q := int32(qTemp)

	for qItr := 0; qItr < int(q); qItr++ {

		split := strings.Split(strings.TrimSpace(readLine(reader)), " ")
		n, err := strconv.ParseInt(split[0], 10, 64)
		checkError(err)
		d12, err := strconv.ParseInt(split[1], 10, 64)
		checkError(err)
		d23, err := strconv.ParseInt(split[2], 10, 64)
		checkError(err)
		d31, err := strconv.ParseInt(split[3], 10, 64)
		checkError(err)

		solve(int(n), int(d12), int(d23), int(d31))
	}
}

func readLine(reader *bufio.Reader) string {
	str, _, err := reader.ReadLine()
	if err == io.EOF {
		return ""
	}

	return strings.TrimRight(string(str), "\r\n")
}

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

package main

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

var _, _, _ = main, rw, do

func main() {
	r, w := bufio.NewReader(os.Stdin), bufio.NewWriter(os.Stdout)
	defer w.Flush()
	rw(r, w)
}

func rw(r io.Reader, w io.Writer) {
	var t int
	fmt.Fscan(r, &t)
	for ti := 0; ti < t; ti++ {
		var n, d12, d23, d31 int
		fmt.Fscan(r, &n, &d12, &d23, &d31)
		w1, w2 := do(n, d12, d23, d31)
		fmt.Fprintln(w, w1)
		for _, v := range w2 {
			fmt.Fprintln(w, v[0], v[1])
		}
	}
}

func do(n, d12, d23, d31 int) (string, [][]int) {
	d := [3][3]int{}
	d[0][1] = d12
	d[1][0] = d12
	d[1][2] = d23
	d[2][1] = d23
	d[0][2] = d31
	d[2][0] = d31
	f := func(x int) (string, [][]int) {
		y := (x + 1) % 3
		z := (x + 2) % 3
		if d[x][y]+d[x][z] == d[y][z] {
			r := [][]int{}
			i := 3
			dxy := d[x][y]
			for k := 0; k < dxy-1; k++ {
				r = append(r, []int{y, i})
				y = i
				i++
			}
			r = append(r, []int{x, y})
			dxz := d[x][z]
			for k := 0; k < dxz-1; k++ {
				r = append(r, []int{i, x})
				x = i
				i++
			}
			r = append(r, []int{x, z})
			for i < n {
				r = append(r, []int{0, i})
				i++
			}
			return "YES", r
		}
		return "NO", nil
	}
	g := func(r [][]int) (string, [][]int) {
		for _, v := range r {
			v[0]++
			v[1]++
			if v[0] == v[1] || v[0] > n || v[1] > n {
				return "NO", nil
			}
		}
		return "YES", r
	}
	for i := 0; i < 3; i++ {
		_, r := f(i)
		if len(r) > 0 {
			return g(r)
		}
	}
	a2 := d12 - d23 + d31
	a := a2 / 2
	b := d12 - a
	c := d31 - a
	if a2 < 0 || a2%2 == 1 || b <= 0 || c <= 0 {
		return "NO", nil
	}
	r := [][]int{}
	i := 3
	h := func(x, a, p int) {
		for k := 0; k < a-1; k++ {
			r = append(r, []int{x, i})
			x = i
			i++
		}
		r = append(r, []int{x, p})
	}
	h(0, a, n-1)
	h(1, b, n-1)
	h(2, c, n-1)
	for i < n-1 {
		r = append(r, []int{0, i})
		i++
	}
	return g(r)
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1+1 > n || d2+d3 > n || d1 > d2+d3 || (d2+d3-d1)%2 == 1 {
			fmt.Fprintln(out, "NO")
		} else if d1 == d2+d3 {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			// fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1+1 > n || d2+d3 > n || d1 > d2+d3 || (d2+d3-d1)%2 == 1 {
			fmt.Fprintln(out, "NO")
		} else if d1 == d2+d3 {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1+1 > n || d1 > d2+d3 || (d2+d3-d1)%2 == 1 {
			fmt.Fprintln(out, "NO")
		} else if d1 == d2+d3 && d1+1 <= n {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			// fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1+1 > n || d1 > d2+d3 {
			fmt.Fprintln(out, "NO")
		} else if d1 == d2+d3 && d1+1 <= n {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			// fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1 == d2+d3 && d1+1 <= n {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			// fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1 == d2+d3 && d1+1 <= n {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1 == d2+d3 {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			// fmt.Fprintln(out, diff, l, s)
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-l, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-l, cnt)
			}
			// fmt.Fprintln(out, "------")
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1 == d2+d3 {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p11, p12, d1, cnt)
			// fmt.Fprintln(out, "------")
			if p11 == p21 {
				// fmt.Fprintln(out, "------1")
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				// fmt.Fprintln(out, "------2")
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			} else if p12 == p21 {
				// fmt.Fprintln(out, "------3")
				cnt = buildTree(out, 4+s-1, p22, d2-s, cnt)
			} else {
				// fmt.Fprintln(out, "------4")
				cnt = buildTree(out, 4+s-1, p21, d2-s, cnt)
			}
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func buildTree(out *bufio.Writer, sp, ep, len, cnt int) int {
	last := sp
	for i := 1; i < len; i++ {
		fmt.Fprintln(out, last, cnt)
		last, cnt = cnt, cnt+1
	}
	fmt.Fprintln(out, last, ep)
	return cnt
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t, n, d1, d2, d3, cnt int
	var p11, p12, p21, p22, p31, p32 int
	fmt.Fscan(in, &t)
	for ; t != 0; t-- {
		fmt.Fscan(in, &n, &d1, &d2, &d3)
		p11, p12, p21, p22, p31, p32 = 1, 2, 2, 3, 3, 1
		cnt = 4
		if d1 < d2 {
			d1, d2 = d2, d1
			p11, p12, p21, p22 = p21, p22, p11, p12
		}
		if d1 < d3 {
			d1, d3 = d3, d1
			p11, p12, p31, p32 = p31, p32, p11, p12
		}
		if d2 < d3 {
			d2, d3 = d3, d2
			p21, p22, p31, p32 = p31, p32, p21, p22
		}

		if d1 == d2+d3 {
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p21, p22, d2, cnt)
			cnt = buildTree(out, p31, p32, d3, cnt)
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else if (((d2 - d3) % 2) == (d1 % 2)) && (d1+d2-d3 <= n) {
			diff := d2 - d3
			l, s := (d1-diff)/2+diff, (d1-diff)/2
			if d2-l < 0 {
				fmt.Fprintln(out, "NO")
				continue
			}
			fmt.Fprintln(out, "YES")
			cnt = buildTree(out, p11, p12, d1, cnt)
			if p11 == p21 {
				cnt = buildTree(out, 4+l-1, p22, d2-l, cnt)
			} else if p11 == p22 {
				cnt = buildTree(out, 4+s-1, p21, d2-s, cnt)
			} else if p12 == p21 {
				cnt = buildTree(out, 4+s-1, p22, d2-s, cnt)
			} else {
				cnt = buildTree(out, 4+l-1, p21, d2-l, cnt)
			}
			for last := 1; cnt <= n; cnt, last = cnt+1, cnt {
				fmt.Fprintln(out, last, cnt)
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0{
			fmt.Fprintln(out, "NO")
			continue
		}
		tt /= 2
		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0{
			fmt.Fprintln(out, "NO")
			continue
		}

		nodes := d1 + d2 + d3 + 1

		if d1 == 0 || d2 == 0 || d3 == 0 {
			nodes--
		}

		if d1 + d2 + d3 + 1 > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5
		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		cur := root
		for ;d1>1;d1--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d1 > 0 {
			fmt.Fprintln(out, cur,  1)
		}

		cur = root
		for ;d2>1;d2--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d2 > 0{
			fmt.Fprintln(out, cur, 2)
		}

		cur = root
		for ;d3>1;d3--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d3 > 0{
			fmt.Fprintln(out, cur, 3)
		}

		cur = 3
		for ; id <= n; id++{
			if cur == 3{
				fmt.Fprintln(out, cur, id)
			}else{
				fmt.Fprintln(out, id - 1, id)
			}
			cur = id
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0{
			fmt.Fprintln(out, "NO")
			continue
		}
		tt /= 2
		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0{
			fmt.Fprintln(out, "NO")
			continue
		}

		if d1 + d2 + d3 + 1 > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5
		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		cur := root
		for ;d1>1;d1--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d1 > 0 {
			fmt.Fprintln(out, cur,  1)
		}

		cur = root
		for ;d2>1;d2--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d2 > 0{
			fmt.Fprintln(out, cur, 2)
		}

		cur = root
		for ;d3>1;d3--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d3 > 0{
			fmt.Fprintln(out, cur, 3)
		}

		cur = 3
		for ; id <= n; id++{
			if cur == 3{
				fmt.Fprintln(out, cur, id)
			}else{
				fmt.Fprintln(out, id - 1, id)
			}
			cur = id
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0{
			fmt.Fprintln(out, "NO")
			continue
		}
		tt /= 2
		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0{
			fmt.Fprintln(out, "NO")
			continue
		}

		if d1 + d2 + d3 + 1 > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5
		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		cur := root
		for ;d1>1;d1--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d1 > 0{
			fmt.Fprintln(out, cur,  1)
		}

		cur = root
		for ;d2>1;d2--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d2 > 0{
			fmt.Fprintln(out, cur, 2)
		}

		cur = root
		for ;d3>1;d3--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d3 > 0{
			fmt.Fprintln(out, cur, 3)
		}

		cur = 3
		for ; id <= n; id++{
			if cur == 3{
				fmt.Fprintln(out, cur, id)
			}else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
	}
}

package main

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

var (
	in = bufio.NewReader(os.Stdin)
	out = bufio.NewWriter(os.Stdout)
)

func ReadInt() int{
	var i int
	fmt.Fscan(in, &i)
	return i
}

func main(){
	defer out.Flush()
	t := ReadInt()
	for ; t > 0; t--{
		n := ReadInt()
		d12, d23, d31 := ReadInt(), ReadInt(), ReadInt()
		tt := d12 + d23 + d31
		if tt % 2 != 0{
			fmt.Fprintln(out, "NO")
			continue
		}
		tt /= 2
		d1, d2, d3 := tt - d23, tt - d31, tt - d12

		if d1 < 0 || d2 < 0 || d3 < 0{
			fmt.Fprintln(out, "NO")
			continue
		}

		if d1 + d2 + d3 + 1 > n{
			fmt.Fprintln(out,"NO")
			continue
		}

		fmt.Fprintln(out, "YES")

		root,id := 4,5
		if d1==0 {
			root=1
			id=4
		}
		if d2==0{
			root=2
			id=4
		}
		if d3==0{
			root=3
			id=4
		}

		cur := root
		for ;d1>1;d1--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d1 > 0{
			fmt.Fprintln(out, cur,  1)
		}

		cur = root
		for ;d2>1;d2--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d2 > 0{
			fmt.Fprintln(out, cur, 2)
		}

		cur = root
		for ;d3>1;d3--{
			if cur == root{
				fmt.Fprintln(out, root, id)
			} else{
				fmt.Fprintln(out, id, id + 1)
			}
			cur = id
			id++
		}
		if d3 > 0{
			fmt.Fprintln(out, cur, 3)
		}

		cur = 3
		for ; id <= n; id++{
			if cur == 3{
				fmt.Fprintln(out, cur, id)
			}else{
				fmt.Println(out, id, id + 1)
			}
			cur = id
			id++
		}
	}
}

package main

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

var in = bufio.NewReader(os.Stdin)
var out = bufio.NewWriter(os.Stdout)
var qq = 0
var cnt = 0

func qwq() {
	cnt++
	var n, d12, d23, d31 int
	// fmt.Fscanf(in, "%d %d %d %d", &n, &d12, &d23, &d31)
	fmt.Fscanln(in, &n, &d12, &d23, &d31)
	// fmt.Fprintln(out, n, d12, d23, d31)
	res := [][2]int{}

	d := (d12 + d31 - d23) / 2
	id := 4
	conn := func(v1, v2, v3, d1, d2 int) {
		la := v1
		for i := 1; i < d1; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		res = append(res, [2]int{la, v2})
		la = v2
		for i := 1; i < d2; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		res = append(res, [2]int{la, v3})
		for id <= n {
			res = append(res, [2]int{1, id})
			id++
		}
	}

	if d12+d23 == d31 {
		conn(1, 2, 3, d12, d23)
	} else if d31+d23 == d12 {
		conn(1, 3, 2, d31, d23)
	} else {
		if (d12+d31 < d23) || (d12+d31-d23)%2 != 0 {
			fmt.Fprintln(out, "NO")
			return
		}
		la := 1
		for i := 0; i < d; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		l2 := la
		for i := 1; i < d12-d; i++ {
			res = append(res, [2]int{l2, id})
			l2 = id
			id++
		}
		res = append(res, [2]int{l2, 2})
		l3 := la
		for i := 1; i < d31-d; i++ {
			res = append(res, [2]int{l3, id})
			l3 = id
			id++
		}
		res = append(res, [2]int{l3, 3})
		for id <= n {
			res = append(res, [2]int{1, id})
			id++
		}
	}
	if qq == 8280 {
		if cnt == 103 {
			fmt.Fprintln(out, n, d12, d23, d31)
			for _, v := range res {
				fmt.Fprintln(out, v[0], v[1])
			}
		}
	} else {
		if id == n+1 {
			fmt.Fprintln(out, "YES")
			for _, v := range res {
				fmt.Fprintln(out, v[0], v[1])
			}
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}
func main() {
	defer out.Flush()
	q := 1
	fmt.Fscanln(in, &q)
	qq = q
	for ; q > 0; q-- {
		qwq()
	}
}

package main

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

var in = bufio.NewReader(os.Stdin)
var out = bufio.NewWriter(os.Stdout)

func qwq() {
	var n, d12, d23, d31 int
	// fmt.Fscanf(in, "%d %d %d %d", &n, &d12, &d23, &d31)
	fmt.Fscanln(in, &n, &d12, &d23, &d31)
	// fmt.Fprintln(out, n, d12, d23, d31)
	res := [][2]int{}

	d := (d12 + d31 - d23) / 2
	id := 4
	conn := func(v1, v2, v3, d1, d2 int) {
		la := v1
		for i := 1; i < d1; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		res = append(res, [2]int{la, v2})
		la = v2
		for i := 1; i < d2; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		res = append(res, [2]int{la, v3})
		for id <= n {
			res = append(res, [2]int{1, id})
			id++
		}
	}

	if d12+d23 == d31 {
		conn(1, 2, 3, d12, d23)
	} else if d31+d23 == d12 {
		conn(1, 3, 2, d31, d23)
	} else {
		if (d12+d31 < d23) || (d12+d31-d23)%2 != 0 {
			fmt.Fprintln(out, "NO")
			return
		}
		la := 1
		for i := 0; i < d; i++ {
			res = append(res, [2]int{la, id})
			la = id
			id++
		}
		l2 := la
		for i := 1; i < d12-d; i++ {
			res = append(res, [2]int{l2, id})
			l2 = id
			id++
		}
		res = append(res, [2]int{l2, 2})
		l3 := la
		for i := 1; i < d31-d; i++ {
			res = append(res, [2]int{l3, id})
			l3 = id
			id++
		}
		res = append(res, [2]int{l3, 3})
		for id <= n {
			res = append(res, [2]int{1, id})
			id++
		}
	}
	if id == n+1 {
		fmt.Fprintln(out, "YES")
		for _, v := range res {
			fmt.Fprintln(out, v[0], v[1])
		}
	} else {
		fmt.Fprintln(out, "NO")
	}
}
func main() {
	defer out.Flush()
	q := 1
	fmt.Fscanln(in, &q)
	for ; q > 0; q-- {
		qwq()
	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

func solve(n, d12, d23, d31 int) {
	var mind, maxd int
	b := false
	i := minInt(d12, d31)

	if i == d12 {
		mind = 2
		maxd = 3
	} else {
		mind = 3
		maxd = 2
	}

	for ; i >= 0; i-- {
		if (d12-i)+(d31-i) == d23 {
			b = true
			break
		}
	}

	if !b {
		fmt.Println("No")
		return
	}
	extra := n - ((i + 1) + (d12 - i) + (d31 - i))

	if extra < 0 {
		fmt.Println("No")
		return
	}

	fmt.Println("Yes")

	src := 1
	if i == minInt(d12, d31) {
		src = pathAToB(1, mind, 3, i)
		src = pathAToB(mind, maxd, src-1, maxInt(d12, d31)-i)
	}
	if 0 < i && i < minInt(d12, d31) {
		src = pathAToB(1, 3+i, 4, i)
		src = pathAToB(3+i, 2, src-1, d12-i)
		src = pathAToB(3+i, 3, src-1, d31-i)
	}

	if i == 0 {
		src = pathAToB(1, 2, 3, d12)
		src = pathAToB(1, 3, src-1, d31)
	}
	for ii := n - extra + 1; ii <= n; ii++ {
		fmt.Println(1, ii)
	}

}
func pathAToB(src, dist, cnt, length int) int {
	a := src
	j := 0
	for j = 1; j < length; j++ {
		fmt.Println(a, cnt+j)
		a = cnt + j
	}
	if length > 0 {
		fmt.Println(a, dist)
	}
	return cnt + j
}
func minInt(a, b int) int {
	if a > b {
		return b
	}
	return a
}
func maxInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	reader := bufio.NewReaderSize(os.Stdin, 16*1024*1024)

	qTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
	checkError(err)
	q := int32(qTemp)

	for qItr := 0; qItr < int(q); qItr++ {

		split := strings.Split(strings.TrimSpace(readLine(reader)), " ")
		n, err := strconv.ParseInt(split[0], 10, 64)
		checkError(err)
		d12, err := strconv.ParseInt(split[1], 10, 64)
		checkError(err)
		d23, err := strconv.ParseInt(split[2], 10, 64)
		checkError(err)
		d31, err := strconv.ParseInt(split[3], 10, 64)
		checkError(err)

		solve(int(n), int(d12), int(d23), int(d31))
	}
}

func readLine(reader *bufio.Reader) string {
	str, _, err := reader.ReadLine()
	if err == io.EOF {
		return ""
	}

	return strings.TrimRight(string(str), "\r\n")
}

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

package main

import (
	"bufio"
	"fmt"
	"io"
	"os"
	"strconv"
	"strings"
)

func solve(n, d12, d23, d31 int) {
	var mind, maxd int
	b := false
	i := minInt(d12, d31)

	if i == d12 {
		mind = 2
		maxd = 3
	} else {
		mind = 3
		maxd = 2
	}

	for ; i >= 0; i-- {
		if (d12-i)+(d31-i) == d23 {
			b = true
			break
		}
	}

	if !b {
		fmt.Println("No")
		return
	}
	extra := n - ((i + 1) + (d12 - i) + (d31 - i))

	if extra < 0 {
		fmt.Println("No")
		return
	}

	fmt.Println("Yes")

	src := 1
	if i == minInt(d12, d31) {
		src = pathAToB(1, mind, 3, i)
		src = pathAToB(mind, maxd, src-1, maxInt(d12, d31)-i)
	}
	if 0 < i && i < minInt(d12, d31) {
		src = pathAToB(1, 3+i, 3, i)
		src = pathAToB(3+i, 2, src-1, d12-i)
		src = pathAToB(3+i, 3, src-1, d31-i)
	}

	if i == 0 {
		src = pathAToB(1, 2, 3, d12)
		src = pathAToB(1, 3, src-1, d31)
	}
	for ii := n - extra + 1; ii <= n; ii++ {
		fmt.Println(1, ii)
	}

}
func pathAToB(src, dist, cnt, length int) int {
	a := src
	j := 0
	for j = 1; j < length; j++ {
		fmt.Println(a, cnt+j)
		a = cnt + j
	}
	if length > 0 {
		fmt.Println(a, dist)
	}
	return cnt + j
}
func minInt(a, b int) int {
	if a > b {
		return b
	}
	return a
}
func maxInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func main() {
	reader := bufio.NewReaderSize(os.Stdin, 16*1024*1024)

	qTemp, err := strconv.ParseInt(strings.TrimSpace(readLine(reader)), 10, 64)
	checkError(err)
	q := int32(qTemp)

	for qItr := 0; qItr < int(q); qItr++ {

		split := strings.Split(strings.TrimSpace(readLine(reader)), " ")
		n, err := strconv.ParseInt(split[0], 10, 64)
		checkError(err)
		d12, err := strconv.ParseInt(split[1], 10, 64)
		checkError(err)
		d23, err := strconv.ParseInt(split[2], 10, 64)
		checkError(err)
		d31, err := strconv.ParseInt(split[3], 10, 64)
		checkError(err)

		solve(int(n), int(d12), int(d23), int(d31))
	}
}

func readLine(reader *bufio.Reader) string {
	str, _, err := reader.ReadLine()
	if err == io.EOF {
		return ""
	}

	return strings.TrimRight(string(str), "\r\n")
}

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

package main

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

var _, _, _ = main, rw, do

func main() {
	r, w := bufio.NewReader(os.Stdin), bufio.NewWriter(os.Stdout)
	defer w.Flush()
	rw(r, w)
}

func rw(r io.Reader, w io.Writer) {
	var t int
	fmt.Fscan(r, &t)
	for ti := 0; ti < t; ti++ {
		var n, d12, d23, d31 int
		fmt.Fscan(r, &n, &d12, &d23, &d31)
		w1, w2 := do(n, d12, d23, d31)
		fmt.Fprintln(w, w1)
		for _, v := range w2 {
			fmt.Fprintln(w, v[0], v[1])
		}
	}
}

func do(n, d12, d23, d31 int) (string, [][]int) {
	d := [3][3]int{}
	d[0][1] = d12
	d[1][0] = d12
	d[1][2] = d23
	d[2][1] = d23
	d[0][2] = d31
	d[2][0] = d31
	f := func(x int) (string, [][]int) {
		y := (x + 1) % 3
		z := (x + 2) % 3
		if d[x][y]+d[x][z] == d[y][z] {
			r := [][]int{}
			i := 3
			dxy := d[x][y]
			for k := 0; k < dxy-1; k++ {
				r = append(r, []int{y, i})
				y = i
				i++
			}
			r = append(r, []int{x, y})
			dxz := d[x][z]
			for k := 0; k < dxz-1; k++ {
				r = append(r, []int{i, x})
				x = i
				i++
			}
			r = append(r, []int{x, z})
			for i < n {
				r = append(r, []int{0, i})
				i++
			}
			return "YES", r
		}
		return "NO", nil
	}
	g := func(r [][]int) [][]int {
		for _, v := range r {
			v[0]++
			v[1]++
		}
		return r
	}
	for i := 0; i < 3; i++ {
		s, r := f(i)
		if len(r) > 0 {
			return s, g(r)
		}
	}
	a2 := d12 - d23 + d31
	a := a2 / 2
	b := d12 - a
	c := d31 - a
	if a2 < 0 || a2%2 == 1 || b <= 0 || c <= 0 {
		return "NO", nil
	}
	r := [][]int{}
	i := 3
	h := func(x, a, p int) {
		for k := 0; k < a-1; k++ {
			r = append(r, []int{x, i})
			x = i
			i++
		}
		r = append(r, []int{x, p})
	}
	h(0, a, n-1)
	h(1, b, n-1)
	h(2, c, n-1)
	for i < n-1 {
		r = append(r, []int{0, i})
		i++
	}
	return "YES", g(r)
}