package main

import (
	"bufio"
	"fmt"
	"os"
)
var a [200005]int
type Node struct{
	v int
	l int
	r int
	left *Node
	right *Node
}
func max(x,y int)int{
	if x>y{
		return x
	}
	return y
}
func min(x,y int)int{
	if x<y{
		return x
	}
	return y
}
func abs(x int)int{
	if x<0{
		return -x
	}
	return x
}
func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t int
	fmt.Fscan(in,&t)
	for t>0{
		t--
		var n, m int
		fmt.Fscan(in,&n,&m)
		a := make([][]int,n+5)
		for i:=0;i<len(a);i++{
			a[i] = make([]int,m+5)
		}
		for i:=1;i<=n;i++{
			for j:=1;j<=m;j++{
				fmt.Fscan(in,&a[i][j])
			}
		}
		fmin := make([][]int,n+5)
		for i:=0;i<len(fmin);i++{
			fmin[i] = make([]int, m+5)
		}
		fmax := make([][]int,n+5)
		for i:=0;i<len(fmax);i++{
			fmax[i] = make([]int,m+5)
		}
		fmax[1][1] = a[1][1]
		fmin[1][1] = a[1][1]
		for i:=1;i<=n;i++{
			for j:=1;j<=m;j++{
				if i==1 && j==1{
					continue
				}
				if i-1>=1 && j-1 >=1{
					fmax[i][j] = a[i][j] + max(fmax[i-1][j],fmax[i][j-1])
					fmin[i][j] = a[i][j] + min(fmin[i-1][j],fmin[i][j-1])
					continue
				}
				if i-1>=1{
					fmax[i][j]=fmax[i-1][j] + a[i][j]
					fmin[i][j]=fmin[i-1][j] + a[i][j]
				}
				if j-1>=1{
					fmax[i][j]=fmax[i][j-1] + a[i][j]
					fmin[i][j]=fmin[i][j-1] + a[i][j]
				}
			}
		}
		if fmax[n][m]<0 || fmin[n][m] > 0 || (n+m)%2==0{
			fmt.Fprintln(out,"NO")
		}else{
			fmt.Fprintln(out,"YES")
		}
	}
}

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, m int
		fmt.Fscan(r, &n, &m)
		a := make([][]int, n)
		for i := 0; i < n; i++ {
			a[i] = make([]int, m)
			for j := 0; j < m; j++ {
				fmt.Fscan(r, &a[i][j])
			}
		}
		w1 := do(n, m, a)
		fmt.Fprintln(w, w1)
	}
}

func do(n, m int, a [][]int) string {
	if (n+m-1)%2 == 1 {
		return "NO"
	}
	b := make([]int, m)
	c := make([]int, m)
	b[0] = a[0][0]
	c[0] = a[0][0]
	min := func(a, b int) int {
		if a < b {
			return a
		} else {
			return b
		}
	}
	max := func(a, b int) int {
		if a > b {
			return a
		} else {
			return b
		}
	}
	for i := range a {
		for j := range a[i] {
			if i > 0 && j > 0 {
				b[j] = min(b[j], b[j-1]) + a[i][j]
				c[j] = max(c[j], c[j-1]) + a[i][j]
			} else if i > 0 {
				b[j] += a[i][j]
				c[j] += a[i][j]
			} else if j > 0 {
				b[j] = b[j-1] + a[i][j]
				c[j] = c[j-1] + a[i][j]
			}
		}
	}
	if b[m-1] > 0 || c[m-1] < 0 {
		return "NO"
	}
	return "YES"
}

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"
	"strings"
)
var wrtr = bufio.NewWriterSize(os.Stdout, 10_000_000)
var rdr = bufio.NewScanner(os.Stdin)
func gs() string  { rdr.Scan(); return rdr.Text() }
func gi() int     { i,e := strconv.Atoi(gs()); if e != nil {panic(e)}; return i }
func gis(n int) []int  { res := make([]int,n); for i:=0;i<n;i++ { res[i] = gi() }; return res }
func gf() float64 { f,e := strconv.ParseFloat(gs(),64); if e != nil {panic(e)}; return f }
func gbs() []byte { return []byte(gs()) }
func gfs(n int) []float64  { res := make([]float64,n); for i:=0;i<n;i++ { res[i] = gf() }; return res }
func gss(n int) []string  { res := make([]string,n); for i:=0;i<n;i++ { res[i] = gs() }; return res }
func gi64() int64     { i,e := strconv.ParseInt(gs(),10,64); if e != nil {panic(e)}; return i }
func gis64(n int) []int64  { res := make([]int64,n); for i:=0;i<n;i++ { res[i] = gi64() }; return res }

func ia(m int) []int { return make([]int,m) }
func iai(m int,v int) []int { a := make([]int,m); for i:=0;i<m;i++ { a[i] = v }; return a }
func twodi(n int,m int,v int) [][]int {
	r := make([][]int,n); for i:=0;i<n;i++ { x := make([]int,m); for j:=0;j<m;j++ { x[j] = v }; r[i] = x }; return r
}
func fill2(m int) ([]int,[]int) { a,b := ia(m),ia(m); for i:=0;i<m;i++ {a[i],b[i] = gi(),gi()}; return a,b }
func fill3(m int) ([]int,[]int,[]int) { a,b,c := ia(m),ia(m),ia(m); for i:=0;i<m;i++ {a[i],b[i],c[i] = gi(),gi(),gi()}; return a,b,c }
func fill4(m int) ([]int,[]int,[]int,[]int) { a,b,c,d := ia(m),ia(m),ia(m),ia(m); for i:=0;i<m;i++ {a[i],b[i],c[i],d[i] = gi(),gi(),gi(),gi()}; return a,b,c,d }
func abs(a int) int { if a < 0 { return -a }; return a }
func rev(a []int) { i,j := 0,len(a)-1; for i < j { a[i],a[j] = a[j],a[i]; i++; j-- } }
func max(a,b int) int { if a > b { return a }; return b }
func min(a,b int) int { if a > b { return b }; return a }
func maxarr(a []int) int { ans := a[0]; for _,aa := range(a) { if aa > ans { ans = aa } }; return ans }
func minarr(a []int) int { ans := a[0]; for _,aa := range(a) { if aa < ans { ans = aa } }; return ans }
func sumarr(a []int) int { ans := 0; for _,aa := range(a) { ans += aa }; return ans }
func zeroarr(a []int) { for i:=0; i<len(a); i++ { a[i] = 0 } }
func powmod(a,e,mod int) int { res, m := 1, a; for e > 0 { if e&1 != 0 { res = res * m % mod }; m = m * m % mod; e >>= 1 }; return res }
func powint(a,e int) int { res, m := 1, a; for e > 0 { if e&1 != 0 { res = res * m }; m = m * m; e >>= 1 }; return res }
func gcd(a,b int) int { for b != 0 { t:=b; b=a%b; a=t }; return a }
func gcdExtended(a,b int) (int,int,int) { if a == 0 { return b,0,1 }; gcd,x1,y1 := gcdExtended(b%a,a); return gcd, y1-(b/a)*x1,x1 }
func modinv(a,m int) (int,bool) { g,x,_ := gcdExtended(a,m); if g != 1 { return 0,false }; return (x % m + m) % m,true  }
func vecintstring(a []int) string { astr := make([]string,len(a)); for i,a := range a { astr[i] = strconv.Itoa(a) }; return strings.Join(astr," ") }
func makefact(n int,mod int) ([]int,[]int) {
	fact,factinv := make([]int,n+1),make([]int,n+1)
	fact[0] = 1; for i:=1;i<=n;i++ { fact[i] = fact[i-1] * i % mod }
	factinv[n] = powmod(fact[n],mod-2,mod); for i:=n-1;i>=0;i-- { factinv[i] = factinv[i+1] * (i+1) % mod }
	return fact,factinv
}

func ia64(m int) []int64 { return make([]int64,m) }
func iai64(m int,v int64) []int64 { a := make([]int64,m); for i:=0;i<m;i++ { a[i] = v }; return a }
func twodi64(n int,m int,v int64) [][]int64 {
	r := make([][]int64,n); for i:=0;i<n;i++ { x := make([]int64,m); for j:=0;j<m;j++ { x[j] = v }; r[i] = x }; return r
}
func fill264(m int) ([]int64,[]int64) { a,b := ia64(m),ia64(m); for i:=0;i<m;i++ {a[i],b[i] = gi64(),gi64()}; return a,b }
func fill364(m int) ([]int64,[]int64,[]int64) { a,b,c := ia64(m),ia64(m),ia64(m); for i:=0;i<m;i++ {a[i],b[i],c[i] = gi64(),gi64(),gi64()}; return a,b,c }
func fill464(m int) ([]int64,[]int64,[]int64,[]int64) { a,b,c,d := ia64(m),ia64(m),ia64(m),ia64(m); for i:=0;i<m;i++ {a[i],b[i],c[i],d[i] = gi64(),gi64(),gi64(),gi64()}; return a,b,c,d }
func abs64(a int64) int64 { if a < 0 { return -a }; return a }
func rev64(a []int64) { i,j := 0,len(a)-1; for i < j { a[i],a[j] = a[j],a[i]; i++; j-- } }
func max64(a,b int64) int64 { if a > b { return a }; return b }
func min64(a,b int64) int64 { if a > b { return b }; return a }
func maxarr64(a []int64) int64 { ans := a[0]; for _,aa := range(a) { if aa > ans { ans = aa } }; return ans }
func minarr64(a []int64) int64 { ans := a[0]; for _,aa := range(a) { if aa < ans { ans = aa } }; return ans }
func sumarr64(a []int64) int64 { ans := int64(0); for _,aa := range(a) { ans += aa }; return ans }
func zeroarr64(a []int64) { for i:=0; i<len(a); i++ { a[i] = 0 } }
func powmod64(a,e,mod int64) int64 { res, m := int64(1), a; for e > 0 { if e&1 != 0 { res = res * m % mod }; m = m * m % mod; e >>= 1 }; return res }
func powint64(a,e int64) int64 { res, m := int64(1), a; for e > 0 { if e&1 != 0 { res = res * m }; m = m * m; e >>= 1 }; return res }
func gcd64(a,b int64) int64 { for b != 0 { t:=b; b=a%b; a=t }; return a }
func gcdExtended64(a,b int64) (int64,int64,int64) { if a == 0 { return b,0,1 }; gcd,x1,y1 := gcdExtended64(b%a,a); return gcd, y1-(b/a)*x1,x1 }
func modinv64(a,m int64) (int64,bool) { g,x,_ := gcdExtended64(a,m); if g != 1 { return 0,false }; return (x % m + m) % m,true  }
func vecint64string(a []int64) string { astr := make([]string,len(a)); for i,a := range a { astr[i] = strconv.FormatInt(a,10) }; return strings.Join(astr," ") }
func makefact64(n int,mod int64) ([]int64,[]int64) {
	fact,factinv := make([]int64,n+1),make([]int64,n+1)
	fact[0] = 1; for i:=1;i<=n;i++ { fact[i] = fact[i-1] * int64(i) % mod }
	factinv[n] = powmod64(fact[n],mod-2,mod); for i:=n-1;i>=0;i-- { factinv[i] = factinv[i+1] * int64(i+1) % mod }
	return fact,factinv
}
func main() {
	//f1, _ := os.Create("cpu.prof"); pprof.StartCPUProfile(f1); defer pprof.StopCPUProfile()
	defer wrtr.Flush()
	infn := ""; if infn == "" && len(os.Args) > 1 {	infn = os.Args[1] }
	if infn != "" {	f, e := os.Open(infn); if e != nil { panic(e) }; rdr = bufio.NewScanner(f) }
	rdr.Split(bufio.ScanWords); rdr.Buffer(make([]byte,1024),1_000_000_000)
	// PROGRAM STARTS HERE
	T := gi();
	for tt:=1;tt<=T;tt++ {
		N,M := gi(),gi(); gr := make([][]int,N); for i:=0;i<N;i++ { gr[i] = gis(M); }
		// Just need to check if zero is in between the max and min and has the right parity
		dpmax := twodi(N,M,-999999999)
		dpmin := twodi(N,M,999999999)
		dpmax[0][0] = gr[0][0]
		dpmin[0][0] = gr[0][0]
		for i:=0;i<N;i++ {
			for j:=0;j<M;j++ {
				if i > 0 { dpmax[i][j] = max(dpmax[i][j],dpmax[i-1][j]+gr[i][j]); dpmin[i][j] = min(dpmin[i][j],dpmin[i-1][j]+gr[i][j]) }
				if j > 0 { dpmax[i][j] = max(dpmax[i][j],dpmax[i][j-1]+gr[i][j]); dpmin[i][j] = min(dpmin[i][j],dpmin[i][j-1]+gr[i][j]) }
			}
		}
		ans := "NO"
		if (N+M) % 2 == 1 && dpmax[N-1][M-1] >= 0 && dpmin[N-1][M-1] <= 0 { ans = "YES" }
		fmt.Fprintln(wrtr,ans)
	}
}

package main

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

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

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

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var T int
	fmt.Fscan(in, &T)
	const N = 1010
	var grid [N][N]int
	var mx [N][N]int
	var mn [N][N]int
	for t := 0; t < T; t++ {
		var n, m int
		fmt.Fscan(in, &n, &m)

		for i := 0; i < n; i++ {
			for j := 0; j < m; j++ {
				fmt.Fscan(in, &grid[i][j])
			}
		}

		mx[0][0], mn[0][0] = grid[0][0], grid[0][0]
		for i := 1; i < n; i++ {
			mx[i][0] = mx[i-1][0] + grid[i][0]
			mn[i][0] = mx[i][0]
		}

		for j := 1; j < m; j++ {
			mx[0][j] = mx[0][j-1] + grid[0][j]
			mn[0][j] = mx[0][j]
		}

		for i := 1; i < n; i++ {
			for j := 1; j < m; j++ {
				mx[i][j] = max(mx[i-1][j], mx[i][j-1]) + grid[i][j]
				mn[i][j] = min(mn[i-1][j], mn[i][j-1]) + grid[i][j]
			}
		}

		if mx[n-1][m-1]%2 != 0 || mn[n-1][m-1] > 0 || mx[n-1][m-1] < 0 {
			fmt.Fprintln(out, "NO")
		} else {
			fmt.Fprintln(out, "YES")
		}
	}
}

package main

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

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

func CF1695C(in io.Reader, out io.Writer) {
	r := bufio.NewReader(in)
	w := bufio.NewWriter(out)
	defer w.Flush()

	var T int64
	fmt.Fscan(r, &T)
	for ; T > 0; T-- {
		var n, m int64
		fmt.Fscan(r, &n, &m)
		arr := make([][]int64, n)
		mn, mx := make([][]int64, n), make([][]int64, n)
		for i := int64(0); i < n; i++ {
			arr[i] = make([]int64, m)
			mn[i], mx[i] = make([]int64, m), make([]int64, m)
			for j := int64(0); j < m; j++ {
				fmt.Fscan(r, &arr[i][j])
			}
		}
		mn[0][0], mx[0][0] = arr[0][0], arr[0][0]
		for i := int64(1); i < n; i++ {
			mx[i][0], mn[i][0] = mx[i-1][0]+arr[i][0], mx[i-1][0]+arr[i][0]
		}
		for  j := int64(1); j < m; j++ {
			mx[0][j], mn[0][j] = mx[0][j - 1] + arr[0][j], mx[0][j - 1] + arr[0][j]
		}

		for i := int64(1); i < n; i++ {
			for j := int64(1); j< m; j++ {
				mx[i][j] = max(mx[i - 1][j], mx[i][j - 1]) + arr[i][j];
				mn[i][j] = min(mn[i - 1][j], mn[i][j - 1]) + arr[i][j];
			}
		}

		if mx[n - 1][m - 1] % 2 == 1|| mn[n - 1][m - 1] > 0 || mx[n - 1][m - 1] < 0 {
			fmt.Fprintln(w, "NO")
		} else {
			fmt.Fprintln(w, "YES")
		}

	}

}

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

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

package main

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

/*
1
4 5
1 -1  1  1  1
1 -1  1 -1 -1
1  1 -1  1  1
1  1 -1  1 -1
---
YES

(1)   (0)     (1)       (2)         (3)
(2)  (-1,1)  (0,2)     (-1,1)     (-2,0,2)
(3) (0,2,4) (-1,1,3)   (0,2,4)    (-1,1,3,5)
(4) (1,3,5) (-2,0,2,4) (-1,1,3,5) (-2,0,2,4)
*/

//goland:noinspection GoUnhandledErrorResult
func solve() {
	var n, m int
	scanf("%d %d\n", &n, &m)

	a := make([][]int, n)

	for r := range a {
		a[r] = make([]int, m)

		for c := 0; c < m; c++ {
			scanf("%d", &a[r][c])
		}
		scanf("\n")
	}

	if (n+m-1)%2 != 0 {
		fmt.Fprintln(writer, "NO")
		return
	}

	mn := make([][]int, n)
	mx := make([][]int, n)

	for r := range a {
		mx[r] = make([]int, m)
		mn[r] = make([]int, m)
	}

	mx[0][0] = a[0][0]

	for c, num := range a[0] {
		mx[0][c] = num
		mn[0][c] = num

		if c != 0 {
			mx[0][c] += mx[0][c-1]
			mn[0][c] += mn[0][c-1]
		}
	}

	for r := 0; r < n; r++ {
		num := a[r][0]

		mx[r][0] = num
		mn[r][0] = num

		if r != 0 {
			mx[r][0] += mx[r-1][0]
			mn[r][0] += mn[r-1][0]
		}
	}

	for r := 1; r < n; r++ {
		for c := 1; c < m; c++ {
			num := a[r][c]

			mx[r][c] = max(mx[r-1][c], mx[r][c-1]) + num
			mn[r][c] = min(mn[r-1][c], mn[r][c-1]) + num
		}
	}

	if 0 >= mn[n-1][m-1] && 0 <= mx[n-1][m-1] {
		fmt.Fprintln(writer, "YES")
	} else {
		fmt.Fprintln(writer, "NO")
	}
}

//goland:noinspection GoUnhandledErrorResult
func main() {
	defer writer.Flush()

	t := 1
	scanf("%d\n", &t)

	for ; t > 0; t-- {
		solve()
	}
}

const maxUint = ^uint(0)

//goland:noinspection GoUnusedConst
const minUint = 0
const maxInt = int(maxUint >> 1)

//goland:noinspection GoUnusedConst
const minInt = -maxInt - 1

var reader = bufio.NewReader(os.Stdin)
var writer = bufio.NewWriter(os.Stdout)

func scanf(f string, a ...interface{}) {
	if _, err := fmt.Fscanf(reader, f, a...); err != nil {
		panic(err)
	}
}

//goland:noinspection GoUnusedFunction
func reversed(s string) string {
	input := []rune(s)
	li := len(input)
	ret := make([]rune, li)
	for i, r := range input {
		ret[li-i-1] = r
	}
	return string(ret)
}

//goland:noinspection GoUnusedFunction
func divCeil(num, div int64) int64 {
	quot := num / div
	if num%div > 0 {
		quot++
	} else if num%div < 0 {
		quot--
	}
	return quot
}

//goland:noinspection GoUnusedFunction
func min(nums ...int) int {
	return nums[minIdx(nums...)]
}

//goland:noinspection GoUnusedFunction
func minIdx(nums ...int) int {
	minNumIdx := 0
	for i, num := range nums {
		if num < nums[minNumIdx] {
			minNumIdx = i
		}
	}

	return minNumIdx
}

//goland:noinspection GoUnusedFunction
func max(nums ...int) int {
	return nums[maxIdx(nums...)]
}

//goland:noinspection GoUnusedFunction
func maxIdx(nums ...int) int {
	maxNumIdx := 0
	for i, num := range nums {
		if num > nums[maxNumIdx] {
			maxNumIdx = i
		}
	}

	return maxNumIdx
}

//goland:noinspection GoUnusedFunction
func sum(nums ...int) (sum int) {
	for _, num := range nums {
		sum += num
	}
	return
}

//goland:noinspection GoUnusedFunction
func abs(num int) int {
	if num < 0 {
		return -num
	}
	return num
}

//goland:noinspection GoUnusedFunction
func isPrime(num int64) bool {
	if num == 2 || num == 3 {
		return true
	}

	if num <= 1 || num%2 == 0 || num%3 == 0 {
		return false
	}

	for i := int64(5); i*i <= num; i += 6 {
		if num%i == 0 || num%(i+2) == 0 {
			return false
		}
	}

	return true
}

//goland:noinspection GoUnusedFunction
func gcd(a, b int) int {
	for b != 0 {
		a, b = b, a%b
	}
	return a
}

//goland:noinspection GoUnusedFunction
func lcm(a, b int) int {
	return abs(a) / gcd(a, b) * abs(b)
}

// Examples:
//	digitAt(1234, -1) -> panic!
//	digitAt(1234, 0) -> 4
//	digitAt(1234, 1) -> 3
//	digitAt(1234, 2) -> 2
//	digitAt(1234, 3) -> 1
//	digitAt(1234, 4) -> panic!
//goland:noinspection GoUnusedFunction
func digitAt(num, pos int) int {
	if num == 0 {
		return 0
	}

	num = abs(num)

	lenNum := int(math.Log10(float64(num))) + 1
	if pos < 0 || pos >= lenNum {
		err := fmt.Sprintf("Out of bound access for digit. Position passed %d, number %d", pos, num)
		panic(err)
	}

	rem := num % int(math.Pow10(pos+1))
	return rem / int(math.Pow10(pos))
}

//goland:noinspection GoUnusedFunction
func factorize(num int64) []int64 {
	factors := make([]int64, 0)

	for ftr := int64(2); ftr*ftr <= num; ftr++ {
		for num%ftr == 0 {
			num /= ftr
			factors = append(factors, ftr)
		}
	}

	if num > 1 {
		factors = append(factors, num)
	}

	return factors
}

package main

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

/*
1
4 5
1 -1  1  1  1
1 -1  1 -1 -1
1  1 -1  1  1
1  1 -1  1 -1
---
YES

(1)   (0)     (1)       (2)         (3)
(2)  (-1,1)  (0,2)     (-1,1)     (-2,0,2)
(3) (0,2,4) (-1,1,3)   (0,2,4)    (-1,1,3,5)
(4) (1,3,5) (-2,0,2,4) (-1,1,3,5) (-2,0,2,4)
*/

//goland:noinspection GoUnhandledErrorResult
func solve() {
	var n, m int
	scanf("%d %d\n", &n, &m)

	a := make([][]int, n)

	for r := range a {
		a[r] = make([]int, m)

		for c := 0; c < m; c++ {
			scanf("%d", &a[r][c])
		}
		scanf("\n")
	}

	if (n+m-1)%2 != 0 {
		fmt.Fprintln(writer, "NO")
		return
	}

	mn := make([][]int, n)
	mx := make([][]int, n)

	for r := range a {
		mx[r] = make([]int, m)
		mn[r] = make([]int, m)
	}

	mx[0][0] = a[0][0]

	for c, num := range a[0] {
		mx[0][c] = num
		mn[0][c] = num

		if c != 0 {
			mx[0][c] += mx[0][c-1]
			mn[0][c] += mn[0][c-1]
		}
	}

	for r := 0; r < n; r++ {
		num := a[r][0]

		mx[r][0] = num
		mn[r][0] = num

		if r != 0 {
			mx[r][0] += mx[r-1][0]
			mn[r][0] += mn[r-1][0]
		}
	}

	for r := 1; r < n; r++ {
		for c := 1; c < m; c++ {
			num := a[r][c]

			mx[r][c] = max(mx[r-1][c], mx[r][c-1]) + num
			mn[r][c] = min(mn[r-1][c], mn[r][c-1]) + num
		}
	}

	if 0 >= mn[n-1][m-1] && 0 <= mx[n-1][m-1] && mx[n-1][m-1]%2 == 0 {
		fmt.Fprintln(writer, "YES")
	} else {
		fmt.Fprintln(writer, "NO")
	}
}

//goland:noinspection GoUnhandledErrorResult
func main() {
	defer writer.Flush()

	t := 1
	scanf("%d\n", &t)

	for ; t > 0; t-- {
		solve()
	}
}

const maxUint = ^uint(0)

//goland:noinspection GoUnusedConst
const minUint = 0
const maxInt = int(maxUint >> 1)

//goland:noinspection GoUnusedConst
const minInt = -maxInt - 1

var reader = bufio.NewReader(os.Stdin)
var writer = bufio.NewWriter(os.Stdout)

func scanf(f string, a ...interface{}) {
	if _, err := fmt.Fscanf(reader, f, a...); err != nil {
		panic(err)
	}
}

//goland:noinspection GoUnusedFunction
func reversed(s string) string {
	input := []rune(s)
	li := len(input)
	ret := make([]rune, li)
	for i, r := range input {
		ret[li-i-1] = r
	}
	return string(ret)
}

//goland:noinspection GoUnusedFunction
func divCeil(num, div int64) int64 {
	quot := num / div
	if num%div > 0 {
		quot++
	} else if num%div < 0 {
		quot--
	}
	return quot
}

//goland:noinspection GoUnusedFunction
func min(nums ...int) int {
	return nums[minIdx(nums...)]
}

//goland:noinspection GoUnusedFunction
func minIdx(nums ...int) int {
	minNumIdx := 0
	for i, num := range nums {
		if num < nums[minNumIdx] {
			minNumIdx = i
		}
	}

	return minNumIdx
}

//goland:noinspection GoUnusedFunction
func max(nums ...int) int {
	return nums[maxIdx(nums...)]
}

//goland:noinspection GoUnusedFunction
func maxIdx(nums ...int) int {
	maxNumIdx := 0
	for i, num := range nums {
		if num > nums[maxNumIdx] {
			maxNumIdx = i
		}
	}

	return maxNumIdx
}

//goland:noinspection GoUnusedFunction
func sum(nums ...int) (sum int) {
	for _, num := range nums {
		sum += num
	}
	return
}

//goland:noinspection GoUnusedFunction
func abs(num int) int {
	if num < 0 {
		return -num
	}
	return num
}

//goland:noinspection GoUnusedFunction
func isPrime(num int64) bool {
	if num == 2 || num == 3 {
		return true
	}

	if num <= 1 || num%2 == 0 || num%3 == 0 {
		return false
	}

	for i := int64(5); i*i <= num; i += 6 {
		if num%i == 0 || num%(i+2) == 0 {
			return false
		}
	}

	return true
}

//goland:noinspection GoUnusedFunction
func gcd(a, b int) int {
	for b != 0 {
		a, b = b, a%b
	}
	return a
}

//goland:noinspection GoUnusedFunction
func lcm(a, b int) int {
	return abs(a) / gcd(a, b) * abs(b)
}

// Examples:
//	digitAt(1234, -1) -> panic!
//	digitAt(1234, 0) -> 4
//	digitAt(1234, 1) -> 3
//	digitAt(1234, 2) -> 2
//	digitAt(1234, 3) -> 1
//	digitAt(1234, 4) -> panic!
//goland:noinspection GoUnusedFunction
func digitAt(num, pos int) int {
	if num == 0 {
		return 0
	}

	num = abs(num)

	lenNum := int(math.Log10(float64(num))) + 1
	if pos < 0 || pos >= lenNum {
		err := fmt.Sprintf("Out of bound access for digit. Position passed %d, number %d", pos, num)
		panic(err)
	}

	rem := num % int(math.Pow10(pos+1))
	return rem / int(math.Pow10(pos))
}

//goland:noinspection GoUnusedFunction
func factorize(num int64) []int64 {
	factors := make([]int64, 0)

	for ftr := int64(2); ftr*ftr <= num; ftr++ {
		for num%ftr == 0 {
			num /= ftr
			factors = append(factors, ftr)
		}
	}

	if num > 1 {
		factors = append(factors, num)
	}

	return factors
}

package main

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

func abs(n int) int {
	if n < 0 {
		return n * -1
	}
	return n
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var T int
	fmt.Fscan(in, &T)
	for t := 0; t < T; t++ {
		var n, m int
		fmt.Fscan(in, &n, &m)

		aa := make([][]int, n)
		for i := 0; i < n; i++ {
			aa[i] = make([]int, m)
			for j := 0; j < m; j++ {
				fmt.Fscan(in, &aa[i][j])
			}
		}

		vis := make([][]bool, n)
		for i := 0; i < n; i++ {
			vis[i] = make([]bool, m)
		}
		var f bool
		var walk func(i, j, tot int)
		walk = func(i, j, tot int) {
			t2 := tot + aa[i][j]
			if f || abs(t2) > (n-i-1)+(m-j-1) {
				return
			}
			vis[i][j] = true
			if i < n-1 && !vis[i+1][j] {
				walk(i+1, j, t2)
			}

			if j < m-1 && !vis[i][j+1] {
				walk(i, j+1, t2)
			}

			if i == n-1 && j == m-1 && t2 == 0 {
				f = true
			}
		}
		walk(0, 0, 0)

		if f {
			fmt.Fprintln(out, "YES")
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

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

func abs(n int) int {
	if n < 0 {
		return n * -1
	}
	return n
}

func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()

	var T int
	fmt.Fscan(in, &T)
	for t := 0; t < T; t++ {
		var n, m int
		fmt.Fscan(in, &n, &m)

		aa := make([][]int, n)
		for i := 0; i < n; i++ {
			aa[i] = make([]int, m)
			for j := 0; j < m; j++ {
				fmt.Fscan(in, &aa[i][j])
			}
		}

		var f bool
		var walk func(i, j, tot int)
		vis := make([]bool, n*m+1)
		walk = func(i, j, tot int) {
			t2 := tot + aa[i][j]
			if f || abs(t2) > (n-i-1)+(m-j-1) || vis[(i*m)+j] {
				return
			}
			vis[(i*m)+j] = true
			if i < n-1 {
				walk(i+1, j, t2)
			}

			if j < m-1 {
				walk(i, j+1, t2)
			}

			if i == n-1 && j == m-1 && t2 == 0 {
				f = true
			}
		}
		walk(0, 0, 0)

		if f {
			fmt.Fprintln(out, "YES")
		} else {
			fmt.Fprintln(out, "NO")
		}
	}
}

package main

import (
	"bufio"
	"fmt"
	"os"
)
var a [200005]int
type Node struct{
	v int
	l int
	r int
	left *Node
	right *Node
}
func max(x,y int)int{
	if x>y{
		return x
	}
	return y
}
func min(x,y int)int{
	if x<y{
		return x
	}
	return y
}
func abs(x int)int{
	if x<0{
		return -x
	}
	return x
}
func build(x *Node, l, r int){
	x.l = l
	x.r = r
	mid := (l+r)>>1
	if l == r{
		x.v=a[mid]
		return
	}
	x.left = &Node{}
	x.right = &Node{}
	build(x.left,l,mid)
	build(x.right,mid+1,r)
	x.v = max(x.left.v,x.right.v)
}
func getMax(x *Node, l, r int) int{
	if(l<=x.l&&r>=x.r){
		return x.v
	}
	if r<x.l||l>x.r{
		return -1
	}
	lv := getMax(x.left,l,r)
	rv := getMax(x.right,l,r)
	return max(lv,rv)
}
var n, m int64
func main() {
	in := bufio.NewReader(os.Stdin)
	out := bufio.NewWriter(os.Stdout)
	defer out.Flush()
	var t int
	fmt.Fscan(in,&t)
	for t>0{
		t--
		var n, m int
		fmt.Fscan(in,&n,&m)
		a := make([][]int,n+5)
		for i:=0;i<len(a);i++{
			a[i] = make([]int,m+5)
		}
		for i:=1;i<=n;i++{
			for j:=1;j<=m;j++{
				fmt.Fscan(in,&a[i][j])
			}
		}
		fmin := make([][]int,n+5)
		for i:=0;i<len(fmin);i++{
			fmin[i] = make([]int, m+5)
		}
		fmax := make([][]int,n+5)
		for i:=0;i<len(fmax);i++{
			fmax[i] = make([]int,m+5)
		}
		fmax[1][1] = a[1][1]
		fmin[1][1] = a[1][1]
		for i:=1;i<=n;i++{
			for j:=1;j<=m;j++{
				if i==1 && j==1{
					continue
				}
				if i-1>=1 && j-1 >=1{
					fmax[i][j] = a[i][j] + max(fmax[i-1][j],fmax[i][j-1])
					fmin[i][j] = a[i][j] + min(fmin[i-1][j],fmin[i][j-1])
					continue
				}
				if i-1>=1{
					fmax[i][j]=fmax[i-1][j] + a[i][j]
					fmin[i][j]=fmin[i-1][j] + a[i][j]
				}
				if j-1>=1{
					fmax[i][j]=fmax[i][j-1] + a[i][j]
					fmin[i][j]=fmin[i][j-1] + a[i][j]
				}
			}
		}
		if fmax[n][m]<0 || fmin[n][m] > 0{
			fmt.Fprintln(out,"NO")
		}else{
			fmt.Fprintln(out,"YES")
		}
	}
}


package main

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

var bufin *bufio.Reader
var bufout *bufio.Writer

var n, m, s, t, e, x, y, w, cnt, budget, c, e1, e2 int
var adj, next, last, idx, weight, trace, num, low, save []int
var visited, bridge, path, removed []bool

func add(x int, y int, i int, w int) {
	adj[e] = y
	idx[e] = i
	weight[e] = w
	next[e] = last[x]
	last[x] = e
	e++
}

func dfs(u int) {
	cnt++
	num[u] = cnt
	low[u] = num[u]

	for i := last[u]; i != -1; i = next[i] {
		if !removed[i] {
			v := adj[i]
			if trace[v] == -1 {
				visited[i] = true
				visited[i^1] = true
				trace[v] = i
				dfs(v)
				if low[u] > low[v] {
					low[u] = low[v]
				}
				if low[v] >= num[v] {
					bridge[i] = true
					bridge[i^1] = true
				}
			} else if !visited[i] {
				if low[u] > num[v] {
					low[u] = num[v]
				}
			}
		}
	}
}

func find(ce int, bg int, oe int) bool {
	trace = make([]int, n)
	num = make([]int, n)
	low = make([]int, n)

	visited = make([]bool, e)
	bridge = make([]bool, e)

	for i := range visited {
		visited[i] = false
		bridge[i] = false
	}

	for i := range trace {
		trace[i] = -1
	}

	trace[s] = s
	cnt = 0

	dfs(s)
	if trace[t] == -1 {
		return false
	}

	path = make([]bool, e)
	for i := range path {
		path[i] = false
	}

	v := t
	for v != s {
		i := trace[v]
		path[i] = true
		path[i^1] = true
		v = adj[i^1]
		if bridge[i] && ((budget == -1) || (bg+weight[i] < budget)) {
			budget = bg + weight[i]
			c = ce
			e1 = idx[i]
			e2 = oe
		}
	}

	return true
}

func solution() {
	removed = make([]bool, e)
	for i := range removed {
		removed[i] = false
	}

	budget = -1
	c = -1
	e1 = -1
	e2 = -1

	if !find(1, 0, -1) {
		fmt.Fprintln(bufout, 0)
		fmt.Fprintln(bufout, 0)
		return
	}

	save = make([]int, e)
	ns := 0
	for i := 0; i < e; i += 2 {
		if path[i] {
			save[ns] = i
			ns++
		}
	}

	for j := 0; j < ns; j++ {
		i := save[j]
		removed[i] = true
		removed[i^1] = true
		find(2, weight[i], idx[i])
		removed[i] = false
		removed[i^1] = false
	}

	fmt.Fprintln(bufout, budget)
	if budget != -1 {
		fmt.Fprintln(bufout, c)
		fmt.Fprint(bufout, e1)
		if c == 2 {
			fmt.Fprint(bufout, " ", e2)
		}
	}
}

func main() {
	bufin = bufio.NewReader(os.Stdin)
	bufout = bufio.NewWriter(os.Stdout)
	defer bufout.Flush()

	fmt.Fscan(bufin, &n, &m, &s, &t)
	s--
	t--

	adj = make([]int, m*2)
	idx = make([]int, m*2)
	weight = make([]int, m*2)
	next = make([]int, m*2)
	last = make([]int, n)

	for i := range last {
		last[i] = -1
	}
	e = 0

	for i := 1; i <= m; i++ {
		fmt.Fscan(bufin, &x, &y, &w)
		x--
		y--
		add(x, y, i, w)
		add(y, x, i, w)
	}

	solution()

}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

var path []int

func findPath(g graph, cur, target int, visited []bool) bool {
	if cur == target {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if findPath(g, e.to, target, visited) {
			path = append(path, e.id)
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup, cost []int) (bool, int) {
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] == tin[e.to] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)
	path = []int{}

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := -1
	ans := []int{}

	tin := make([]int, n)
	fup := make([]int, n)

	for _, id := range path {
		for i := 0; i < n; i++ {
			tin[i] = 0
			fup[i] = 0
		}

		curTime = 1
		found, bridgeID := findCheapestBridge(g, s, -1, t, id, tin, fup, cost)

		if bridgeID == -1 {
			if !found && (best == -1 || cost[id] < best) {
				best = cost[id]
				ans = []int{id}
			}
		} else {
			if best == -1 || (cost[id]+cost[bridgeID] < best) {
				best = cost[id] + cost[bridgeID]
				ans = []int{id, bridgeID}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

package main

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

var bufin *bufio.Reader
var bufout *bufio.Writer

var n, m, s, t, e, x, y, w, cnt, budget, c, e1, e2, removed, np, ns int
var adj, next, last, idx, weight, trace, num, low, path, save []int
var visited, bridge []bool

func add(x int, y int, i int, w int) {
	adj[e] = y
	idx[e] = i
	weight[e] = w
	next[e] = last[x]
	last[x] = e
	e++
}

func dfs(u int) {
	cnt++
	num[u] = cnt
	low[u] = num[u]

	for i := last[u]; i != -1; i = next[i] {
		if (i != removed) && ((i ^ 1) != removed) {
			v := adj[i]
			if trace[v] == -1 {
				visited[i] = true
				visited[i^1] = true
				trace[v] = i
				dfs(v)
				if low[u] > low[v] {
					low[u] = low[v]
				}
				if low[v] >= num[v] {
					bridge[i] = true
					bridge[i^1] = true
				}
			} else if !visited[i] {
				if low[u] > num[v] {
					low[u] = num[v]
				}
			}
		}
	}
}

func find(ce int, bg int) bool {
	for i := range visited {
		visited[i] = false
		bridge[i] = false
	}

	for i := range trace {
		trace[i] = -1
	}

	trace[s] = s
	cnt = 0

	dfs(s)
	if trace[t] == -1 {
		return false
	}

	np = 0
	v := t

	for v != s {
		i := trace[v]
		path[np] = i
		np++
		v = adj[i^1]
		if bridge[i] && ((budget == -1) || (bg+weight[i] < budget)) {
			budget = bg + weight[i]
			c = ce
			e1 = idx[i]
			if removed >= 0 {
				e2 = idx[removed]
			}
		}
	}

	return true
}

func solution() {
	trace = make([]int, n)
	num = make([]int, n)
	low = make([]int, n)
	path = make([]int, n)
	save = make([]int, n)

	visited = make([]bool, e)
	bridge = make([]bool, e)

	removed = -1
	budget = -1
	c = -1
	e1 = -1
	e2 = -1

	if !find(1, 0) {
		fmt.Fprintln(bufout, 0)
		fmt.Fprintln(bufout, 0)
		return
	}

	ns = np
	for i, val := range path {
		save[i] = val
	}

	for j := 0; j < ns; j++ {
		removed = save[j]
		find(2, weight[removed])
	}

	fmt.Fprintln(bufout, budget)
	if budget != -1 {
		fmt.Fprintln(bufout, c)
		fmt.Fprint(bufout, e1)
		if c == 2 {
			fmt.Fprint(bufout, " ", e2)
		}
	}
}

func main() {
	bufin = bufio.NewReader(os.Stdin)
	bufout = bufio.NewWriter(os.Stdout)
	defer bufout.Flush()

	fmt.Fscan(bufin, &n, &m, &s, &t)
	s--
	t--

	adj = make([]int, m*2)
	idx = make([]int, m*2)
	weight = make([]int, m*2)
	next = make([]int, m*2)
	last = make([]int, n)

	for i := range last {
		last[i] = -1
	}
	e = 0

	for i := 1; i <= m; i++ {
		fmt.Fscan(bufin, &x, &y, &w)
		x--
		y--
		add(x, y, i, w)
		add(y, x, i, w)
	}

	solution()

}

package main

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

var bufin *bufio.Reader
var bufout *bufio.Writer

const maxn = 1000
const maxm = 30000

var n, m, s, t, e, cnt, closed, p, q, budget, e1, e2 int
var adj, idx, next, weight [maxm*2 + 1]int
var last, trace, num, low, path [maxn + 1]int

func add(i int, x int, y int, w int) {
	idx[e] = i
	adj[e] = y
	weight[e] = w
	next[e] = last[x]
	last[x] = e
	e++
}

func dfs(x int) {
	cnt++
	num[x] = cnt
	low[x] = cnt

	for i := last[x]; i != -1; i = next[i] {
		if (i != closed) && ((i ^ 1) != closed) {
			y := adj[i]
			if trace[y] == -1 {
				trace[y] = i
				dfs(y)
				if low[x] > low[y] {
					low[x] = low[y]
				}
			} else if trace[x] != (i ^ 1) {
				if low[x] > num[y] {
					low[x] = num[y]
				}
			}
		}
	}
}

func find(track bool) bool {
	for i := 1; i <= n; i++ {
		trace[i] = -1
	}

	trace[s] = 0
	cnt = 0
	dfs(s)

	if trace[t] == -1 {
		return false
	}

	if track {
		p = 0
	}
	y := t

	for y != s {
		i := trace[y]

		if track {
			path[p] = i
			p++
		}

		if low[y] >= num[y] {
			cost := weight[i]
			if closed != -1 {
				cost += weight[closed]
			}
			if (budget == -1) || (cost < budget) {
				budget = cost
				e1 = idx[i]
				if closed != -1 {
					e2 = idx[closed]
				}
			}
		}

		y = adj[i^1]
	}

	return true
}

func main() {
	bufin = bufio.NewReader(os.Stdin)
	bufout = bufio.NewWriter(os.Stdout)
	defer bufout.Flush()

	fmt.Fscan(bufin, &n, &m, &s, &t)

	e = 0
	for i := 1; i <= n; i++ {
		last[i] = -1
	}

	var x, y, w int
	for i := 1; i <= m; i++ {
		fmt.Fscan(bufin, &x, &y, &w)
		add(i, x, y, w)
		add(i, y, x, w)
	}

	closed = -1
	budget = -1
	e1 = -1
	e2 = -1

	if !find(true) {
		fmt.Fprintln(bufout, 0)
		fmt.Fprintln(bufout, 0)
	} else {
		for i := 0; i < p; i++ {
			closed = path[i]
			find(false)
		}

		fmt.Fprintln(bufout, budget)
		if budget != -1 {
			if e2 == -1 {
				fmt.Fprintln(bufout, 1)
				fmt.Fprintln(bufout, e1)
			} else {
				fmt.Fprintln(bufout, 2)
				fmt.Fprintln(bufout, e1, e2)
			}
		}
	}
}

package main

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

var (
	reader *bufio.Reader = bufio.NewReader(os.Stdin)
	writer *bufio.Writer = bufio.NewWriter(os.Stdout)
	Debug                = false
)

func Printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }
func Scanf(f string, a ...interface{})  { fmt.Fscanf(reader, f, a...) }

func Dprint(format string, a ...interface{}) {
	if Debug {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

type road struct {
	w   int // weight
	idx int // index of the road (starting from 0)
}

var disRoad *road

func (r *road) String() string {
	return fmt.Sprintf("<%d:%d>", r.idx+1, r.w)
}

type roadPtr struct {
	v int
	r *road
}

var (
	n, m    int
	s, t    int
	adj     [][]roadPtr
	visited []bool
)

func main() {
	defer writer.Flush()

	// Read inpput.
	Scanf("%d %d\n", &n, &m)
	Scanf("%d %d\n", &s, &t)
	s--
	t--

	adj = make([][]roadPtr, n)
	for i := 0; i < m; i++ {
		var xi, yi, wi int
		Scanf("%d %d %d\n", &xi, &yi, &wi)
		xi--
		yi--
		// TODO(stefan): idx: i+1?
		r := road{w: wi, idx: i}
		adj[xi] = append(adj[xi], roadPtr{yi, &r})
		adj[yi] = append(adj[yi], roadPtr{xi, &r})
	}

	// Run DFS(s, t) and try to remove each of the roads. Then run bridge-finding algo.
	visited = make([]bool, n)
	roads := dfs(s, t)

	if len(roads) == 0 {
		// They are already disconnected.
		Printf("0\n0\n")
		return
	}

	Dprint("%v", roads)
	runBridges(roads)

	if len(minRoads) == 0 {
		// Impossible to disconnect.
		Printf("-1")
		return
	}

	Printf("%d\n%d\n", minCost, len(minRoads))
	for _, r := range minRoads {
		Printf("%d ", r.idx+1)
	}
}

// run dfs from start, where previous node is prev and terminating at end.
// It will return list of roads from start to end including both.
// If we can't get from start to end, it will return empty list.
func dfs(start int, end int) []*road {
	visited[start] = true

	for _, nex := range adj[start] {
		if visited[nex.v] {
			// We are only interested in unvisited nodes.
			continue
		}

		if nex.v == end {
			visited[nex.v] = true
			return []*road{nex.r}
		}

		roads := dfs(nex.v, end)
		if len(roads) > 0 {
			return append([]*road{nex.r}, roads...)
		}
	}

	return nil
}

var (
	time    int
	times   []int
	low     []int
	bridges []*road

	minCost  = math.MaxInt32
	minRoads []*road
)

func runBridges(roads []*road) {
	// For every path in paths, try to disable this path and run dfs2 that finds bridges.
	for _, r := range roads {
		// Initialize dfs stuff.
		time = 1
		times = make([]int, n)
		low = make([]int, n)
		for i := 0; i < n; i++ {
			low[i] = math.MaxInt32
		}
		bridges = nil

		disRoad = r
		connected := findBridges(s, nil, t)
		Dprint("road=%v, bridges=%v, low=%v", r, bridges, low)

		if connected {
			// s and t are still connected after removing road.
			for _, br := range bridges {
				cost := disRoad.w + br.w
				if cost < minCost {
					minCost = cost
					minRoads = []*road{r, br}
				}
			}
		} else {
			// s and t are disconnected.
			cost := disRoad.w
			if cost < minCost {
				minCost = cost
				minRoads = []*road{r}
			}
		}
	}
}

// findBridges returns list of bridges, that is edges which removal would cause s and t to disconnect.
// It returns true if end is reachable from start. There should be only one way that contains all the bridges.
func findBridges(start int, prev *road, end int) bool {
	times[start] = time
	low[start] = time
	time++
	foundEnd := false
	for _, nex := range adj[start] {
		// Dprint(" >> dfs(%d) analyze %v", start+1, nex.r)
		if nex.r == disRoad {
			// This road was explicitly disabled in runBridges.
			continue
		}
		if nex.r == prev {
			// Do not look at parent road in DFS tree.
			continue
		}
		nexFoundEnd := false
		// Dprint("   >> not disabled and not prev")
		if times[nex.v] == 0 {
			// Dprint("     >> running DFS")
			// We haven't visited nex.v, so visit it.
			nexFoundEnd = findBridges(nex.v, nex.r, end)
			foundEnd = foundEnd || nexFoundEnd
		}
		if low[nex.v] < low[start] {
			// Update low either from child or back edge.
			low[start] = low[nex.v]
		}
		if nexFoundEnd && low[nex.v] > times[start] && foundEnd {
			// this is a bridge from s to t.
			bridges = append(bridges, nex.r)
		}
	}

	if start == end {
		return true
	}
	return foundEnd
}

package main

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

var (
	reader *bufio.Reader = bufio.NewReader(os.Stdin)
	writer *bufio.Writer = bufio.NewWriter(os.Stdout)
	Debug                = false
)

func Printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }
func Scanf(f string, a ...interface{})  { fmt.Fscanf(reader, f, a...) }

func Dprint(format string, a ...interface{}) {
	if Debug {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

type road struct {
	w   int // weight
	idx int // index of the road (starting from 0)
}

var disRoad *road

func (r *road) String() string {
	return fmt.Sprintf("<%d:%d>", r.idx+1, r.w)
}

type roadPtr struct {
	v int
	r *road
}

var (
	n, m    int
	s, t    int
	adj     [][]roadPtr
	visited []bool
)

func main() {
	defer writer.Flush()

	// Read inpput.
	Scanf("%d %d\n", &n, &m)
	Scanf("%d %d\n", &s, &t)
	s--
	t--

	adj = make([][]roadPtr, n)
	for i := 0; i < m; i++ {
		var xi, yi, wi int
		Scanf("%d %d %d\n", &xi, &yi, &wi)
		xi--
		yi--
		// TODO(stefan): idx: i+1?
		r := road{w: wi, idx: i}
		adj[xi] = append(adj[xi], roadPtr{yi, &r})
		adj[yi] = append(adj[yi], roadPtr{xi, &r})
	}

	// Run DFS(s, t) and try to remove each of the roads. Then run bridge-finding algo.
	visited = make([]bool, n)
	roads := dfs(s, t)

	if len(roads) == 0 {
		// They are already disconnected.
		Printf("0\n0\n")
		return
	}

	Dprint("%v", roads)
	runBridges(roads)

	if len(minRoads) == 0 {
		// Impossible to disconnect.
		Printf("-1")
		return
	}

	Printf("%d\n%d\n", minCost, len(minRoads))
	for _, r := range minRoads {
		Printf("%d ", r.idx+1)
	}
}

// run dfs from start, where previous node is prev and terminating at end.
// It will return list of roads from start to end including both.
// If we can't get from start to end, it will return empty list.
func dfs(start int, end int) []*road {
	visited[start] = true

	for _, nex := range adj[start] {
		if visited[nex.v] {
			// We are only interested in unvisited nodes.
			continue
		}

		if nex.v == end {
			visited[nex.v] = true
			return []*road{nex.r}
		}

		roads := dfs(nex.v, end)
		if len(roads) > 0 {
			return append([]*road{nex.r}, roads...)
		}
	}

	return nil
}

var (
	time    int
	times   []int
	low     []int
	bridges []*road

	minCost  = math.MaxInt32
	minRoads []*road
)

func runBridges(roads []*road) {
	// For every path in paths, try to disable this path and run dfs2 that finds bridges.
	for _, r := range roads {
		// Initialize dfs stuff.
		time = 1
		times = make([]int, n)
		low = make([]int, n)
		for i := 0; i < n; i++ {
			low[i] = math.MaxInt32
		}
		bridges = nil

		disRoad = r
		connected := findBridges(s, nil, t)
		Dprint("road=%v, bridges=%v, low=%v", r, bridges, low)

		if connected {
			// s and t are still connected after removing road.
			for _, br := range bridges {
				cost := disRoad.w + br.w
				if cost < minCost {
					minCost = cost
					minRoads = []*road{r, br}
				}
			}
		} else {
			// s and t are disconnected.
			cost := disRoad.w
			if cost < minCost {
				minCost = cost
				minRoads = []*road{r}
			}
		}
	}
}

// findBridges returns list of bridges, that is edges which removal would cause s and t to disconnect.
// It returns true if end is reachable from start. There should be only one way that contains all the bridges.
func findBridges(start int, prev *road, end int) bool {
	times[start] = time
	low[start] = time
	time++
	foundEnd := false
	for _, nex := range adj[start] {
		// Dprint(" >> dfs(%d) analyze %v", start+1, nex.r)
		if nex.r == disRoad {
			// This road was explicitly disabled in runBridges.
			continue
		}
		if nex.r == prev {
			// Do not look at parent road in DFS tree.
			continue
		}
		nexFoundEnd := false
		// Dprint("   >> not disabled and not prev")
		if times[nex.v] == 0 {
			// Dprint("     >> running DFS")
			// We haven't visited nex.v, so visit it.
			nexFoundEnd = findBridges(nex.v, nex.r, end)
			foundEnd = foundEnd || nexFoundEnd
		}
		if low[nex.v] < low[start] {
			// Update low either from child or back edge.
			low[start] = low[nex.v]
		}
		if nexFoundEnd && low[nex.v] > low[start] && foundEnd {
			// this is a bridge from s to t.
			bridges = append(bridges, nex.r)
		}
	}

	if start == end {
		return true
	}
	return foundEnd
}

package main

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

var (
	reader *bufio.Reader = bufio.NewReader(os.Stdin)
	writer *bufio.Writer = bufio.NewWriter(os.Stdout)
	Debug                = false
)

func Printf(f string, a ...interface{}) { fmt.Fprintf(writer, f, a...) }
func Scanf(f string, a ...interface{})  { fmt.Fscanf(reader, f, a...) }

func Dprint(format string, a ...interface{}) {
	if Debug {
		fmt.Fprintf(os.Stderr, format+"\n", a...)
	}
}

type road struct {
	w   int // weight
	idx int // index of the road (starting from 0)
}

var disRoad *road

func (r *road) String() string {
	return fmt.Sprintf("<%d:%d>", r.idx+1, r.w)
}

type roadPtr struct {
	v int
	r *road
}

var (
	n, m    int
	s, t    int
	adj     [][]roadPtr
	visited []bool
)

func main() {
	defer writer.Flush()

	// Read inpput.
	Scanf("%d %d\n", &n, &m)
	Scanf("%d %d\n", &s, &t)
	s--
	t--

	adj = make([][]roadPtr, n)
	for i := 0; i < m; i++ {
		var xi, yi, wi int
		Scanf("%d %d %d\n", &xi, &yi, &wi)
		xi--
		yi--
		// TODO(stefan): idx: i+1?
		r := road{w: wi, idx: i}
		adj[xi] = append(adj[xi], roadPtr{yi, &r})
		adj[yi] = append(adj[yi], roadPtr{xi, &r})
	}

	// Run DFS(s, t) and try to remove each of the roads. Then run bridge-finding algo.
	visited = make([]bool, n)
	roads := dfs(s, t)

	if len(roads) == 0 {
		// They are already disconnected.
		Printf("0\n\n")
		return
	}

	Dprint("%v", roads)
	runBridges(roads)

	if len(minRoads) == 0 {
		// Impossible to disconnect.
		Printf("-1")
		return
	}

	Printf("%d\n%d\n", minCost, len(minRoads))
	for _, r := range minRoads {
		Printf("%d ", r.idx+1)
	}
}

// run dfs from start, where previous node is prev and terminating at end.
// It will return list of roads from start to end including both.
// If we can't get from start to end, it will return empty list.
func dfs(start int, end int) []*road {
	visited[start] = true

	for _, nex := range adj[start] {
		if visited[nex.v] {
			// We are only interested in unvisited nodes.
			continue
		}

		if nex.v == end {
			visited[nex.v] = true
			return []*road{nex.r}
		}

		roads := dfs(nex.v, end)
		if len(roads) > 0 {
			return append([]*road{nex.r}, roads...)
		}
	}

	return nil
}

var (
	time    int
	times   []int
	low     []int
	bridges []*road

	minCost  = math.MaxInt32
	minRoads []*road
)

func runBridges(roads []*road) {
	// For every path in paths, try to disable this path and run dfs2 that finds bridges.
	for _, r := range roads {
		// Initialize dfs stuff.
		time = 1
		times = make([]int, n)
		low = make([]int, n)
		for i := 0; i < n; i++ {
			low[i] = math.MaxInt32
		}
		bridges = nil

		disRoad = r
		connected := findBridges(s, nil, t)
		Dprint("road=%v, bridges=%v, low=%v", r, bridges, low)

		if connected {
			// s and t are still connected after removing road.
			for _, br := range bridges {
				cost := disRoad.w + br.w
				if cost < minCost {
					minCost = cost
					minRoads = []*road{r, br}
				}
			}
		} else {
			// s and t are disconnected.
			cost := disRoad.w
			if cost < minCost {
				minCost = cost
				minRoads = []*road{r}
			}
		}
	}
}

// findBridges returns list of bridges, that is edges which removal would cause s and t to disconnect.
// It returns true if end is reachable from start. There should be only one way that contains all the bridges.
func findBridges(start int, prev *road, end int) bool {
	times[start] = time
	low[start] = time
	time++
	foundEnd := false
	for _, nex := range adj[start] {
		// Dprint(" >> dfs(%d) analyze %v", start+1, nex.r)
		if nex.r == disRoad {
			// This road was explicitly disabled in runBridges.
			continue
		}
		if nex.r == prev {
			// Do not look at parent road in DFS tree.
			continue
		}
		nexFoundEnd := false
		// Dprint("   >> not disabled and not prev")
		if times[nex.v] == 0 {
			// Dprint("     >> running DFS")
			// We haven't visited nex.v, so visit it.
			nexFoundEnd = findBridges(nex.v, nex.r, end)
			foundEnd = foundEnd || nexFoundEnd
		}
		if low[nex.v] < low[start] {
			// Update low either from child or back edge.
			low[start] = low[nex.v]
		}
		if nexFoundEnd && low[nex.v] > low[start] && foundEnd {
			// this is a bridge from s to t.
			bridges = append(bridges, nex.r)
		}
	}

	if start == end {
		return true
	}
	return foundEnd
}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

const inf = 1 << 30

var path []int

func findPath(g graph, cur, t int, visited []bool) bool {
	if cur == t {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if findPath(g, e.to, t, visited) {
			path = append(path, e.id)
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup, cost []int) (bool, int) {
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] > tin[cur] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)
	path = []int{}

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := inf
	ans := []int{}

	tin := make([]int, n)
	fup := make([]int, n)

	for _, id := range path {
		for i := 0; i < n; i++ {
			tin[i] = 0
			fup[i] = 0
		}

		curTime = 1
		_, c := findCheapestBridge(g, s, -1, t, id, tin, fup, cost)

		if c == -1 {
			if tin[t] == 0 && cost[id] < best {
				best = cost[id]
				ans = []int{id}
			}
		} else {
			if cost[id]+cost[c] < best {
				best = cost[id] + cost[c]
				ans = []int{id, c}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

const inf = 1 << 30

var path []int

func findPath(g graph, cur, t int, visited []bool) bool {
	if cur == t {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if findPath(g, e.to, t, visited) {
			path = append(path, e.id)
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup []int, cost []int) (bool, int) {
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] > tin[cur] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)
	path = []int{}

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := inf
	ans := []int{}

	tin := make([]int, n)
	fup := make([]int, n)

	for _, id := range path {
		for i := 0; i < n; i++ {
			tin[i] = 0
			fup[i] = 0
		}

		curTime = 1
		found, c := findCheapestBridge(g, s, -1, t, id, tin, fup, cost)
		if found && c != -1 {
			if cost[id]+cost[c] < best {
				best = cost[id] + cost[c]
				ans = []int{id, c}
			}
		} else {
			if !found && cost[id] < best {
				best = cost[id]
				ans = []int{id}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

const inf = 1 << 30

var path []int

func findPath(g graph, cur, t int, visited []bool) bool {
	if cur == t {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if !visited[e.to] && findPath(g, e.to, t, visited) {
			path = append(path, e.id)
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup []int, cost []int) (bool, int) {
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] > tin[cur] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)
	path = []int{}

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := inf
	ans := []int{}

	tin := make([]int, n)
	fup := make([]int, n)

	for _, id := range path {
		for i := 0; i < n; i++ {
			tin[i] = 0
			fup[i] = 0
		}

		curTime = 1
		found, c := findCheapestBridge(g, s, -1, t, id, tin, fup, cost)
		if found && c != -1 {
			if cost[id]+cost[c] < best {
				best = cost[id] + cost[c]
				ans = []int{id, c}
			}
		} else {
			if !found && cost[id] < best {
				best = cost[id]
				ans = []int{id}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

const inf = 1 << 30

var path []int

func findPath(g graph, cur, t int, visited []bool) bool {
	if cur == t {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if findPath(g, e.to, t, visited) {
			path = append(path, e.id)
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup, cost []int) (bool, int) {
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] > tin[cur] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)
	path = []int{}

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := inf
	ans := []int{}

	tin := make([]int, n)
	fup := make([]int, n)

	for _, id := range path {
		for i := 0; i < n; i++ {
			tin[i] = 0
			fup[i] = 0
		}

		curTime = 1
		found, c := findCheapestBridge(g, s, -1, t, id, tin, fup, cost)

		if c == -1 {
			if !found && cost[id] < best {
				best = cost[id]
				ans = []int{id}
			}
		} else {
			if cost[id]+cost[c] < best {
				best = cost[id] + cost[c]
				ans = []int{id, c}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

const inf = 1 << 30

func findPath(g graph, cur, t int, visited []bool) bool {
	if cur == t {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if !visited[e.to] && findPath(g, e.to, t, visited) {
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup, visited, cost []int) (bool, int) {
	visited[cur] = 1
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, visited, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] > tin[cur] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := inf
	ans := []int{}

	if m < 3000 {
		for i := 0; i < m; i++ {
			tin := make([]int, n)
			fup := make([]int, n)
			visited := make([]int, n)
			curTime = 1
			found, c := findCheapestBridge(g, s, -1, t, i, tin, fup, visited, cost)
			if found && c != -1 {
				if cost[i]+cost[c] < best {
					best = cost[i] + cost[c]
					ans = []int{i, c}
				}
			} else {
				if !found && cost[i] < best {
					best = cost[i]
					ans = []int{i}
				}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}

package main

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

type edge struct {
	to, cost, id int
}

type graph [][]edge

const inf = 1 << 30

var path []int

func findPath(g graph, cur, target int, visited []bool) bool {
	if cur == target {
		return true
	}
	if visited[cur] {
		return false
	}
	visited[cur] = true
	for _, e := range g[cur] {
		if findPath(g, e.to, target, visited) {
			path = append(path, e.id)
			return true
		}
	}
	return false
}

var curTime = 0

func findCheapestBridge(g graph, cur, pi, target, forb int, tin, fup, cost []int) (bool, int) {
	tin[cur] = curTime
	fup[cur] = curTime
	curTime++

	can := cur == target
	idBest := -1
	for _, e := range g[cur] {
		if e.id == forb || e.id == pi {
			continue
		}
		if tin[e.to] != 0 {
			fup[cur] = min(fup[cur], tin[e.to])
		} else {
			c, id := findCheapestBridge(g, e.to, e.id, target, forb, tin, fup, cost)
			if id != -1 {
				if idBest == -1 || cost[id] < cost[idBest] {
					idBest = id
				}
			}
			if fup[e.to] == tin[e.to] && c {
				if idBest == -1 || e.cost < cost[idBest] {
					idBest = e.id
				}
			}
			can = can || c

			fup[cur] = min(fup[cur], fup[e.to])
		}
	}

	return can, idBest
}

func main() {
	cin := NewReader()

	n := cin.NextInt()
	m := cin.NextInt()
	s := cin.NextInt() - 1
	t := cin.NextInt() - 1

	g := make(graph, n)
	cost := make([]int, m)
	for i := 0; i < m; i++ {
		u := cin.NextInt() - 1
		v := cin.NextInt() - 1
		c := cin.NextInt()
		g[u] = append(g[u], edge{v, c, i})
		g[v] = append(g[v], edge{u, c, i})
		cost[i] = c
	}

	visited := make([]bool, n)
	path = []int{}

	if !findPath(g, s, t, visited) {
		fmt.Printf("0\n0\n")
		return
	}

	best := inf
	ans := []int{}

	tin := make([]int, n)
	fup := make([]int, n)

	for _, id := range path {
		for i := 0; i < n; i++ {
			tin[i] = 0
			fup[i] = 0
		}

		curTime = 1
		found, c := findCheapestBridge(g, s, -1, t, id, tin, fup, cost)

		if c == -1 {
			if !found && cost[id] < best {
				best = cost[id]
				ans = []int{id}
			}
		} else {
			if cost[id]+cost[c] < best {
				best = cost[id] + cost[c]
				ans = []int{id, c}
			}
		}
	}

	if len(ans) > 0 {
		fmt.Printf("%d\n%d\n", best, len(ans))
		for _, it := range ans {
			fmt.Printf("%d ", it+1)
		}
		fmt.Println()
	} else {
		fmt.Printf("-1\n")
	}
}

// Reader is a fast input for programming competitions
type Reader struct {
	scanner *bufio.Scanner
}

// NewReader ...
func NewReader() *Reader {
	var reader Reader
	reader.scanner = bufio.NewScanner(os.Stdin)
	reader.scanner.Split(bufio.ScanWords)
	return &reader
}

// NextInt ...
func (r *Reader) NextInt() int {
	r.scanner.Scan()
	res, _ := strconv.Atoi(r.scanner.Text())
	return res
}

func min(x, y int) int {
	if x < y {
		return x
	}
	return y
}