package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
var n int
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
/*	vertices := []Vertex{}
	haveIn := make(map[Vertex]bool)

	for key := range g.Outs {
		vertices = append(vertices, key)
		haveIn[key] = true
		for vertex, _ := range g.Outs[key] {
			_, ok := haveIn[vertex]
			if ok == false {
				vertices = append(vertices, vertex)
				fmt.Println(vertex, "   !")
			}
		}
	}
	return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}

	/*if n<90000 {
		haveV := false
		for _, item := range g.Ins[succ] {
			if item == v {
				haveV = true
				break
			}
		}
		if haveV == false {
			g.Ins[succ] = append(g.Ins[succ], v)
		}
	}*/

	if _, ok:= g.Outs[v][succ] ; ok ==false{
		g.Ins[succ] = append(g.Ins[succ], v)
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
		delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
		delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	//dfn := make(map[Vertex]int)
	//low := make(map[Vertex]int)
	dfn := make([]int, n+5)
	low := make([]int, n+5)
	belong := make([]int, n+5)
	in := make([]bool, n+5)

	cnt := 0
	//belong := make(map[Vertex]int)
	//in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	//scc := []SCC{}
	//vertices := g.Vertices()
	index := 0
	for v:=1 ; v<=n; v++ {
		if dfn[v] == 0 {
			s1 := []Vertex{{v}}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x.Value.(int)] == 0 {
					index = index + 1
					dfn[x.Value.(int)] = index
					low[x.Value.(int)] = index
					s2 = append(s2, x)
					in[x.Value.(int)] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next.Value.(int)] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next.Value.(int)] == true {
							if low[x.Value.(int)] > dfn[next.Value.(int)] {
								low[x.Value.(int)] = dfn[next.Value.(int)]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x.Value.(int)] > low[next.Value.(int)] {
								low[x.Value.(int)] = low[next.Value.(int)]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x.Value.(int)] == dfn[x.Value.(int)] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t.Value.(int)] = false
							belong[t.Value.(int)] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make([]int64, n+5)
	nway:=make([]int64, n+5)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				//ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		//scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}
	for v :=1; v<=n; v++ {
		id := belong[v]
		if cost[v]<minc[id] {
			minc[id]=cost[v];
			nway[id]=1;
		} else {
			if cost[v] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}

	fmt.Println(sum,sumn)

	return nil
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
		for y, _ := range g.Outs[x] {
			if low[x] != low[y] {
				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
			}
		}
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{0},Vertex{1},"")
	g.Link(Vertex{1},Vertex{2},"")
	g.Link(Vertex{2},Vertex{3},"")
	g.Link(Vertex{3},Vertex{2},"")
	g.Link(Vertex{3},Vertex{7},"")
	g.Link(Vertex{7},Vertex{3},"")
	g.Link(Vertex{2},Vertex{6},"")
	g.Link(Vertex{7},Vertex{6},"")
	g.Link(Vertex{5},Vertex{6},"")
	g.Link(Vertex{6},Vertex{5},"")
	g.Link(Vertex{1},Vertex{5},"")
	g.Link(Vertex{4},Vertex{5},"")
	g.Link(Vertex{4},Vertex{0},"")
	g.Link(Vertex{1},Vertex{4},"")
	// init done ==================================
	// scc ========================================
	scc := g.StronglyConnectedComponents()
	fmt.Println(len(scc))
	fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"0"},Vertex{"1"},"aa")
	g.Link(Vertex{"0"},Vertex{"1"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"1"},Vertex{"2"},"cc")
	g.Link(Vertex{"2"},Vertex{"3"},"")

//	g.UnLink(Vertex{"0"},Vertex{"1"})
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	fmt.Println(g.Vertices())
	xxx := g.MapVertices(canonicalModelName)
	fmt.Println(xxx.Ins)
	fmt.Println(xxx.Outs)
	//fmt.Println("!!!!!!!")
	fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"A"},Vertex{"B"},"aa")
	g.Link(Vertex{"A"},Vertex{"B"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"B"},Vertex{"C"},"cc")
	g.Link(Vertex{"C"},Vertex{"D"},"")
	dg, remap := g.RenumberGraph()
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	//fmt.Println(dg.Ins)
	//fmt.Println(dg.Outs)

	xx := dg.MapVertices(remap)
	fmt.Println(xx.Ins)
	fmt.Println(xx.Outs)*/

	/*var connections [][]int
	connections = append (connections, []int{0,1})
	connections = append (connections, []int{1,2})
	connections = append (connections, []int{2,0})
	connections = append (connections, []int{1,3})
	fmt.Println(criticalConnections(4,connections))*/
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		g.Link(Vertex{a}, Vertex{b}, "")
	}
	g.StronglyConnectedComponents()
}

//package main
//
//import (
//	"bufio"
//	"fmt"
//	"os"
//)
//
//// Edge is a intermediate representation of edge on DirectedGraph
//type Edge struct {
//	From  Vertex
//	To    Vertex
//	Value Rel // raw value of edge
//}
//type Vertex struct {
//	Value interface{}
//}
//var cost []int64
//var n int
//type Rel string
//type DirectedGraph struct {
//	Outs map[Vertex]map[Vertex][]Rel
//	Ins  map[Vertex][]Vertex
//}
//
//// Vertices returns the set of all vertices in graph
//func (g *DirectedGraph) Vertices() []Vertex {
//	vertices := []Vertex{}
//
//	for key := range g.Outs {
//		vertices = append(vertices, key)
//	}
//	return vertices
///*	vertices := []Vertex{}
//	haveIn := make(map[Vertex]bool)
//
//	for key := range g.Outs {
//		vertices = append(vertices, key)
//		haveIn[key] = true
//		for vertex, _ := range g.Outs[key] {
//			_, ok := haveIn[vertex]
//			if ok == false {
//				vertices = append(vertices, vertex)
//				fmt.Println(vertex, "   !")
//			}
//		}
//	}
//	return vertices*/
//}
//
//// In returns inbound vertices to v in graph g
//func (g *DirectedGraph) In(v Vertex) []Vertex {
//	_, ok := g.Ins[v]
//	if !ok {
//		return []Vertex{}
//	} else {
//		return g.Ins[v]
//	}
//}
//
//// Out returns outbound vertices from v in graph g
//func (g *DirectedGraph) Out(v Vertex) []Vertex {
//	_, ok := g.Outs[v]
//	if !ok {
//		return []Vertex{}
//	}
//
//	vertices := []Vertex{}
//
//	for key := range g.Outs[v] {
//		vertices = append(vertices, key)
//	}
//	return vertices
//}
//
//// Edges returns the edge between two vertices
//func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
//	_, oka := g.Outs[a]
//	_, okb := g.Ins[b]
//	if !oka || !okb {
//		return nil
//	}
//
//	_, ok := g.Outs[a][b]
//	if !ok {
//		return nil
//	}
//
//	edges := []Edge{}
//	for _, rel := range g.Outs[a][b] {
//		edges = append(edges, Edge{
//			From:  a,
//			To:    b,
//			Value: rel,
//		})
//	}
//	return edges
//}
//
//// Link links two vertices relationship
//func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
//	_, ok := g.Outs[v]
//	if !ok {
//		g.Outs[v] = make(map[Vertex][]Rel)
//	}
//	_, ok = g.Outs[succ]
//	if !ok {
//		g.Outs[succ] = make(map[Vertex][]Rel)
//	}
//
//	_, ok = g.Ins[v]
//	if !ok {
//		g.Ins[v] = []Vertex{}
//	}
//	_, ok = g.Ins[succ]
//	if !ok {
//		g.Ins[succ] = []Vertex{}
//	}
//
//	haveRel := false
//	for _, item := range g.Outs[v][succ] {
//		if item == rel {
//			haveRel = true
//			break
//		}
//	}
//	if haveRel == false {
//		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
//	}
//
//	/*if n<90000 {
//		haveV := false
//		for _, item := range g.Ins[succ] {
//			if item == v {
//				haveV = true
//				break
//			}
//		}
//		if haveV == false {
//			g.Ins[succ] = append(g.Ins[succ], v)
//		}
//	}*/
//
//	if _, ok:= g.Outs[v][succ] ; ok ==false{
//		g.Ins[succ] = append(g.Ins[succ], v)
//	}
//}
//
//// LinkToAll links x to all ys
//func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
//	for _, y := range ys {
//		g.Link(x, y, rel)
//	}
//}
//
//// LinkAllTo links all xs to y
//func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
//	for _, x := range xs {
//		g.Link(x, y, rel)
//	}
//}
//
//func (g *DirectedGraph) UnLink(a, b Vertex) {
//	delete(g.Outs[a], b)
//	/*if len(g.Outs[a]) == 0 {
//		delete(g.Outs, a)
//	}*/
//
//	for id , vertex := range g.Ins[b] {
//		if vertex == a {
//			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
//			break
//		}
//	}
//	/*if len(g.Ins[b]) == 0 {
//		delete(g.Ins, b)
//	}*/
//}
//
//// Fork implements `forked` semantics on DirectedGraph
//func (g *DirectedGraph) Fork() *DirectedGraph {
//	return g
//	//return deepcopy.Copy(g).(*DirectedGraph)
//	//panic("impl me")
//}
//// IntersectionRel returns the union of res1 and res2
//func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
//	rel := []Rel{}
//	for _, rel1 := range rels1 {
//		both := false
//		for _, rel2 := range rels2{
//			if rel1 == rel2 {
//				both = true
//				break
//			}
//		}
//		if both == true {
//			rel = append(rel, rel1)
//		}
//	}
//	return rel
//}
//
//// ProjectRelationship filters a graph to just those edges with the given relationship
//func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
//	fg := g.Fork()
//
//	vertices := fg.Vertices()
//	for _, x := range vertices {
//		_, ok := g.Outs[x]
//		if ok == true {
//			for y, _:= range g.Outs[x] {
//				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
//				fg.UnLink(x, y)
//				for _, item := range rels {
//					fg.Link(x, y, item)
//				}
//			}
//		}
//	}
//
//	return fg
//}
//
//// FilterRelationships filters a graph g to just those edges which intersect with the given set of
////  relationships
//func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
//	fg := g.Fork()
//
//	vertices := fg.Vertices()
//	for _, x := range vertices {
//		_, ok := g.Outs[x]
//		if ok == true {
//			for y, _:= range g.Outs[x] {
//				rels := IntersectionRel(g.Outs[x][y], rels)
//				fg.UnLink(x, y)
//				for _, item := range rels {
//					fg.Link(x, y, item)
//				}
//			}
//		}
//	}
//
//	return fg
//}
//
//// BfsOut searches from a vertices set, returns all vertices searchable
//// search to downstream vertices from `out` edges
//func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
//	queue := initV
//	V := []Vertex{}
//	haveVisited := make(map[Vertex]bool)
//	for _, vertex := range initV {
//		haveVisited[vertex] = true
//		V = append(V, vertex)
//	}
//
//	for len(queue) > 0 {
//		cur := queue[0]
//		if haveVisited[cur] == false {
//			haveVisited[cur] = true
//			V = append(V, cur)
//		}
//		queue = queue[1:]
//
//		for next, _ := range g.Outs[cur] {
//			if haveVisited[next] == true {
//				continue
//			}
//			queue = append(queue, next)
//		}
//	}
//	return V
//}
//
//// BfsIn searches from a vertices set, returns all vertices searchable
//// search to upstream vertices from `in` edges
//func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
//	queue := initV
//	V := []Vertex{}
//	haveVisited := make(map[Vertex]bool)
//	for _, vertex := range initV {
//		haveVisited[vertex] = true
//		V = append(V, vertex)
//	}
//
//	for len(queue) > 0 {
//		cur := queue[0]
//		if haveVisited[cur] == false {
//			haveVisited[cur] = true
//			V = append(V, cur)
//		}
//		queue = queue[1:]
//
//		for _, next := range g.Ins[cur] {
//			if haveVisited[next] == true {
//				continue
//			}
//			queue = append(queue, next)
//		}
//	}
//	return V
//}
//
//// Bfs searches from a vertices set, returns all vertices searchable
//// out = true means search to downstream vertices from `out` edges
//// out = false means search to upstream vertices from `in` edges
//func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
//	if out == true {
//		return g.BfsOut(initV)
//	} else {
//		return g.BfsIn(initV)
//	}
//}
//
//// SCC indexes all vertices of a strongly connected component
//type SCC struct {
//	Vertices []Vertex
//}
//
//// StronglyConnectedComponents finds all strongly connected components
//func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
//	//dfn := make(map[Vertex]int)
//	//low := make(map[Vertex]int)
//	dfn := make([]int, n+5)
//	low := make([]int, n+5)
//	belong := make([]int, n+5)
//	in := make([]bool, n+5)
//
//
//	cnt := 0
//	//belong := make(map[Vertex]int)
//	//in := make(map[Vertex]bool)
//	tag := make(map[Vertex]map[Vertex]bool)
//	s2 := []Vertex{}
//	//scc := []SCC{}
//	//vertices := g.Vertices()
//	index := 0
//	for v:=1 ; v<=n; v++ {
//		if dfn[v] == 0 {
//			s1 := []Vertex{{v}}
//			//index := 0
//			for len(s1) > 0 {
//				x := s1[len(s1)-1]
//				s1 = s1[:len(s1)-1]
//				if dfn[x.Value.(int)] == 0 {
//					index = index + 1
//					dfn[x.Value.(int)] = index
//					low[x.Value.(int)] = index
//					s2 = append(s2, x)
//					in[x.Value.(int)] = true;
//				}
//				finish := true
//				for next, _ := range g.Outs[x] {
//					//fmt.Println("************")
//					if dfn[next.Value.(int)] == 0 {
//						s1 = append(s1, x)
//						s1 = append(s1, next)
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						tag[x][next] = true
//						finish = false
//						break
//					} else {
//						if in[next.Value.(int)] == true {
//							if low[x.Value.(int)] > dfn[next.Value.(int)] {
//								low[x.Value.(int)] = dfn[next.Value.(int)]
//							}
//						}
//					}
//				}
//				if finish == true {
//					//fmt.Println("??????????")
//					for next, _ := range g.Outs[x] {
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						if tag[x][next] == true {
//							if low[x.Value.(int)] > low[next.Value.(int)] {
//								low[x.Value.(int)] = low[next.Value.(int)]
//							}
//						}
//					}
//					//fmt.Println("!!!!!!!!!!!!")
//					if low[x.Value.(int)] == dfn[x.Value.(int)] {
//						var t Vertex
//						cnt = cnt + 1
//						for {
//							t = s2[len(s2)-1]
//							s2 = s2[:len(s2)-1]
//							in[t.Value.(int)] = false
//							belong[t.Value.(int)] = cnt;
//							if t == x {
//								break
//							}
//						}
//					}
//				}
//			}
//		}
//	}
//	//fmt.Println(cnt, "!!!!!")
//
//	minc:=make([]int64, n+5)
//	nway:=make([]int64, n+5)
//
//	var sum,sumn int64
//	sum=0
//	sumn=1
//
//	/*for i := 1; i <= cnt; i++ {
//		ts := SCC{
//			Vertices: []Vertex{},
//		}
//		minc[i]=2147483647
//		for _, v := range vertices {
//			if belong[v] == i {
//				//ts.Vertices = append(ts.Vertices, v)
//				if cost[v.Value.(int)]<minc[i] {
//					minc[i]=cost[v.Value.(int)];
//					nway[i]=1;
//				} else {
//					if cost[v.Value.(int)] == minc[i] {
//						nway[i]++;
//					}
//				}
//			}
//		}
//		//scc = append(scc, ts)
//		sum+=minc[i];
//		sumn=(sumn*nway[i])%1000000007;
//	}*/
//	for i := 1; i <= cnt; i++ {
//		minc[i]=2147483647
//	}
//	for v :=1; v<=n; v++ {
//		id := belong[v]
//		if cost[v]<minc[id] {
//			minc[id]=cost[v];
//			nway[id]=1;
//		} else {
//			if cost[v] == minc[id] {
//				nway[id]++;
//			}
//		}
//	}
//	for i := 1; i <= cnt; i++ {
//		sum+=minc[i];
//		sumn=(sumn*nway[i])%1000000007;
//	}
//
//	fmt.Println(sum,sumn)
//
//	return nil
//}
//
//// MapVertices takes a function of vertices, returns graph with all
////  vertices mapped via f
//func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
//	//fmt.Println(f("consistent-view"))
//	fg := NewDirectedGraph()
//
//	vertices := g.Vertices()
//	for _, x := range vertices {
//		_, ok := g.Outs[x]
//		if ok == true {
//			for y, _:= range g.Outs[x] {
//				rels := g.Outs[x][y]
//				for _, item := range rels {
//					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
//				}
//			}
//		}
//	}
//
//	return fg
//}
//
//var canonicalModelNames = map[string]string{
//	"consistent-view":         "PL-2+",
//	"conflict-serializable":   "PL-3",
//	"cursor-stability":        "PL-CS",
//	"forward-consistent-view": "PL-FCV",
//	"monotonic-snapshot-read": "PL-MSR",
//	"monotonic-view":          "PL-2L",
//	"read-committed":          "PL-2",
//	"read-uncommitted":        "PL-1",
//	"repeatable-read":         "PL-2.99",
//	"serializable":            "PL-3",
//	"snapshot-isolation":      "PL-SI",
//	"strict-serializable":     "PL-SS",
//	"update-serializable":     "PL-3U",
//	"0": "A",
//	"1": "B",
//	"2": "C",
//}
//
//// canonicalModelName can be applied to DirectedGraph.MapVertices
//func canonicalModelName(name interface{}) interface{} {
//	if cname, ok := canonicalModelNames[name.(string)]; ok {
//		return cname
//	}
//	return name
//}
//
//// NewDirectedGraph returns a empty DirectedGraph
//func NewDirectedGraph() *DirectedGraph {
//	var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	return &g
//}
//
//// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
////  rewritten Graph, and a vector of the original vertices for reconstruction.
//// That means if we apply MapVertices to dg with remap, it can recover to g again
//func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
//	dg := NewDirectedGraph()
//	ref := make(map[Vertex]int)
//	numberToVertices := make(map[interface{}]interface{})
//	vertices := g.Vertices()
//
//	for id, v := range vertices {
//		ref[v] = id
//		numberToVertices[id] = v.Value
//	}
//
//	for _, x := range vertices {
//		for y, rels := range g.Outs[x] {
//			for _, rel := range rels{
//				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
//			}
//		}
//	}
//
//	return dg, func(number interface{}) interface{} {
//		return numberToVertices[number]
//	}
//}
//
//func (g *DirectedGraph) scctest() [][]int {
//	dfn := make(map[Vertex]int)
//	low := make(map[Vertex]int)
//	cnt := 0
//	belong := make(map[Vertex]int)
//	in := make(map[Vertex]bool)
//	tag := make(map[Vertex]map[Vertex]bool)
//	s2 := []Vertex{}
//	vertices := g.Vertices()
//	ans := [][]int{}
//	father := make(map[Vertex]Vertex)
//	vv := Vertex{-1}
//	index := 0
//	for _, v := range vertices {
//		if dfn[v] == 0 {
//			s1 := []Vertex{v}
//			father[v] = vv
//			for len(s1) > 0 {
//				x := s1[len(s1)-1]
//				s1 = s1[:len(s1)-1]
//				if dfn[x] == 0 {
//					index = index + 1
//					dfn[x] = index
//					low[x] = index
//					s2 = append(s2, x)
//					in[x] = true;
//				}
//				finish := true
//				for next, _ := range g.Outs[x] {
//					if dfn[next] == 0 {
//						s1 = append(s1, x)
//						s1 = append(s1, next)
//						father[next]=x
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						tag[x][next] = true
//						finish = false
//						break
//					} else {
//						if in[next] == true {
//							if low[x] > dfn[next] {
//								low[x] = dfn[next]
//								//fmt.Println("!!!!!!!")
//								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
//							}
//						}
//					}
//				}
//				if finish == true {
//					for next, _ := range g.Outs[x] {
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						if tag[x][next] == true {
//							if low[x] > low[next] {
//								low[x] = low[next]
//								//fmt.Println("!!!!!!")
//								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
//							}
//						}
//					}
//					if low[x] == dfn[x] {
//						var t Vertex
//						cnt = cnt + 1
//						for {
//							t = s2[len(s2)-1]
//							s2 = s2[:len(s2)-1]
//							in[t] = false
//							belong[t] = cnt;
//							if t == x {
//								break
//							}
//						}
//					}
//				}
//			}
//		}
//	}
//	for i := 1; i <= cnt; i++ {
//		ts := SCC{
//			Vertices: []Vertex{},
//		}
//		for _, v := range vertices {
//			if belong[v] == i {
//				ts.Vertices = append(ts.Vertices, v)
//			}
//		}
//		//fmt.Println(ts)
//	}
//
//	/*for _, x := range vertices{
//		for y, _ := range g.Outs[x] {
//			if low[x] != low[y] {
//				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
//			}
//		}
//	}*/
//	for _, i:= range vertices{
//		v:= father[i]
//		//fmt.Println(i , "  " ,v )
//		if v != vv {
//			fmt.Println(low[i]," ",dfn[v])
//			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
//		}
//	}
//
//	return ans
//}
//
//
//func criticalConnections(n int, connections [][]int) [][]int {
//	g := NewDirectedGraph()
//	for _, b := range connections{
//		g.Link(Vertex{b[0]},Vertex{b[1]},"")
//		g.Link(Vertex{b[1]},Vertex{b[0]},"")
//	}
//
//	return g.scctest()
//}
//
//func main () {
//	/*var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	g.Link(Vertex{0},Vertex{1},"")
//	g.Link(Vertex{1},Vertex{2},"")
//	g.Link(Vertex{2},Vertex{3},"")
//	g.Link(Vertex{3},Vertex{2},"")
//	g.Link(Vertex{3},Vertex{7},"")
//	g.Link(Vertex{7},Vertex{3},"")
//	g.Link(Vertex{2},Vertex{6},"")
//	g.Link(Vertex{7},Vertex{6},"")
//	g.Link(Vertex{5},Vertex{6},"")
//	g.Link(Vertex{6},Vertex{5},"")
//	g.Link(Vertex{1},Vertex{5},"")
//	g.Link(Vertex{4},Vertex{5},"")
//	g.Link(Vertex{4},Vertex{0},"")
//	g.Link(Vertex{1},Vertex{4},"")
//	// init done ==================================
//	// scc ========================================
//	scc := g.StronglyConnectedComponents()
//	fmt.Println(len(scc))
//	fmt.Println(scc)*/
//	//(5, 6) (7, 3, 2) (4, 1, 0)
//	// scc done ===================================
//
//
//	/*var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	g.Link(Vertex{"0"},Vertex{"1"},"aa")
//	g.Link(Vertex{"0"},Vertex{"1"},"bb")
//	//g.Link(Vertex{"0"},Vertex{"2"},"")
//	g.Link(Vertex{"1"},Vertex{"2"},"cc")
//	g.Link(Vertex{"2"},Vertex{"3"},"")
//
////	g.UnLink(Vertex{"0"},Vertex{"1"})
//	fmt.Println(g.Ins)
//	fmt.Println(g.Outs)
//	fmt.Println(g.Vertices())
//	xxx := g.MapVertices(canonicalModelName)
//	fmt.Println(xxx.Ins)
//	fmt.Println(xxx.Outs)
//	//fmt.Println("!!!!!!!")
//	fmt.Println(xxx.Vertices())*/
//
//	/*var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	g.Link(Vertex{"A"},Vertex{"B"},"aa")
//	g.Link(Vertex{"A"},Vertex{"B"},"bb")
//	//g.Link(Vertex{"0"},Vertex{"2"},"")
//	g.Link(Vertex{"B"},Vertex{"C"},"cc")
//	g.Link(Vertex{"C"},Vertex{"D"},"")
//	dg, remap := g.RenumberGraph()
//	fmt.Println(g.Ins)
//	fmt.Println(g.Outs)
//	//fmt.Println(dg.Ins)
//	//fmt.Println(dg.Outs)
//
//	xx := dg.MapVertices(remap)
//	fmt.Println(xx.Ins)
//	fmt.Println(xx.Outs)*/
//
//
//	/*var connections [][]int
//	connections = append (connections, []int{0,1})
//	connections = append (connections, []int{1,2})
//	connections = append (connections, []int{2,0})
//	connections = append (connections, []int{1,3})
//	fmt.Println(criticalConnections(4,connections))*/
//	var m int
//	in := bufio.NewReader(os.Stdin)
//
//	fmt.Fscan(in, &n)
//	//fmt.Scan(&n)
//	cost = make([]int64, n+5)
//	g := NewDirectedGraph()
//	for i:=1 ; i<=n; i++ {
//		fmt.Fscan(in, &cost[i])
//
//		_, ok := g.Outs[Vertex{i}]
//		if !ok {
//			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
//		}
//		_, ok = g.Ins[Vertex{i}]
//		if !ok {
//			g.Ins[Vertex{i}] = []Vertex{}
//		}
//
//	}
//	fmt.Fscan(in, &m)
//	var a,b int
//	for i:=1 ; i<=m; i++ {
//		fmt.Fscan(in, &a)
//		fmt.Fscan(in, &b)
//		g.Link(Vertex{a}, Vertex{b}, "")
//	}
//	g.StronglyConnectedComponents()
//}
package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
	/*  vertices := []Vertex{}
	    haveIn := make(map[Vertex]bool)

	    for key := range g.Outs {
	        vertices = append(vertices, key)
	        haveIn[key] = true
	        for vertex, _ := range g.Outs[key] {
	            _, ok := haveIn[vertex]
	            if ok == false {
	                vertices = append(vertices, vertex)
	                fmt.Println(vertex, "   !")
	            }
	        }
	    }
	    return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}

	/*if n<90000 {
	    haveV := false
	    for _, item := range g.Ins[succ] {
	        if item == v {
	            haveV = true
	            break
	        }
	    }
	    if haveV == false {
	        g.Ins[succ] = append(g.Ins[succ], v)
	    }
	}*/

	if _, ok:= g.Outs[v][succ] ; ok ==false{
		g.Ins[succ] = append(g.Ins[succ], v)
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
	    delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
	    delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make(map[int]int64)
	nway:=make(map[int]int64)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	scc := make([]SCC, cnt)
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}

	for _, v := range vertices {
		/*if belong[v] == i {
			ts.Vertices = append(ts.Vertices, v)
			if cost[v.Value.(int)]<minc[i] {
				minc[i]=cost[v.Value.(int)];
				nway[i]=1;
			} else {
				if cost[v.Value.(int)] == minc[i] {
					nway[i]++;
				}
			}
		}*/
		id := belong[v]
		scc[id-1].Vertices = append(scc[id-1].Vertices, v)
		if cost[v.Value.(int)]<minc[id] {
			minc[id]=cost[v.Value.(int)];
			nway[id]=1;
		} else {
			if cost[v.Value.(int)] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
				sum+=minc[i];
				sumn=(sumn*nway[i])%1000000007;
			}
	fmt.Println(sum,sumn)

	return scc
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
	    for y, _ := range g.Outs[x] {
	        if low[x] != low[y] {
	            ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
	        }
	    }
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	  g.Ins = make(map[Vertex][]Vertex)
	  g.Outs = make(map[Vertex]map[Vertex][]Rel)
	  g.Link(Vertex{0},Vertex{1},"")
	  g.Link(Vertex{1},Vertex{2},"")
	  g.Link(Vertex{2},Vertex{3},"")
	  g.Link(Vertex{3},Vertex{2},"")
	  g.Link(Vertex{3},Vertex{7},"")
	  g.Link(Vertex{7},Vertex{3},"")
	  g.Link(Vertex{2},Vertex{6},"")
	  g.Link(Vertex{7},Vertex{6},"")
	  g.Link(Vertex{5},Vertex{6},"")
	  g.Link(Vertex{6},Vertex{5},"")
	  g.Link(Vertex{1},Vertex{5},"")
	  g.Link(Vertex{4},Vertex{5},"")
	  g.Link(Vertex{4},Vertex{0},"")
	  g.Link(Vertex{1},Vertex{4},"")
	  // init done ==================================
	  // scc ========================================
	  scc := g.StronglyConnectedComponents()
	  fmt.Println(len(scc))
	  fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	    g.Ins = make(map[Vertex][]Vertex)
	    g.Outs = make(map[Vertex]map[Vertex][]Rel)
	    g.Link(Vertex{"0"},Vertex{"1"},"aa")
	    g.Link(Vertex{"0"},Vertex{"1"},"bb")
	    //g.Link(Vertex{"0"},Vertex{"2"},"")
	    g.Link(Vertex{"1"},Vertex{"2"},"cc")
	    g.Link(Vertex{"2"},Vertex{"3"},"")

	//  g.UnLink(Vertex{"0"},Vertex{"1"})
	    fmt.Println(g.Ins)
	    fmt.Println(g.Outs)
	    fmt.Println(g.Vertices())
	    xxx := g.MapVertices(canonicalModelName)
	    fmt.Println(xxx.Ins)
	    fmt.Println(xxx.Outs)
	    //fmt.Println("!!!!!!!")
	    fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	  g.Ins = make(map[Vertex][]Vertex)
	  g.Outs = make(map[Vertex]map[Vertex][]Rel)
	  g.Link(Vertex{"A"},Vertex{"B"},"aa")
	  g.Link(Vertex{"A"},Vertex{"B"},"bb")
	  //g.Link(Vertex{"0"},Vertex{"2"},"")
	  g.Link(Vertex{"B"},Vertex{"C"},"cc")
	  g.Link(Vertex{"C"},Vertex{"D"},"")
	  dg, remap := g.RenumberGraph()
	  fmt.Println(g.Ins)
	  fmt.Println(g.Outs)
	  //fmt.Println(dg.Ins)
	  //fmt.Println(dg.Outs)

	  xx := dg.MapVertices(remap)
	  fmt.Println(xx.Ins)
	  fmt.Println(xx.Outs)*/

	/*var connections [][]int
	  connections = append (connections, []int{0,1})
	  connections = append (connections, []int{1,2})
	  connections = append (connections, []int{2,0})
	  connections = append (connections, []int{1,3})
	  fmt.Println(criticalConnections(4,connections))*/
	var n int
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		g.Link(Vertex{a}, Vertex{b}, "")
	}
	g.StronglyConnectedComponents()
}

package main

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

type node struct {
    cur, pre int
}

var edge [300010]node
var head [100010]int
var cnt, time int

func Init() {
    for i := 1; i <= 100000; i++ {
        head[i] = -1
    }
    ans2 = 1
}

func addEdge(from, cur int) {
    edge[cnt].cur = cur
    edge[cnt].pre = head[from]
    head[from] = cnt
    cnt++
}

var low, dfn, instack, stack [100010]int
var cost [100010]int64
var ans1, ans2 int64
var idx int

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

func tarjan(u int) {
    time++
    low[u], dfn[u] = time, time
    stack[idx+1], idx = u, idx+1
    instack[u] = 1
    for i := head[u]; i != -1; i = edge[i].pre {
        v := edge[i].cur
        if dfn[v] == 0 {
            tarjan(v)
            low[u] = min(low[u], low[v])
        } else if instack[v] == 1 {
            low[u] = min(low[u], dfn[v])
        }
    }
    if dfn[u] == low[u] {
        tmp := stack[idx]
        instack[tmp] = 0
        idx = idx - 1
        Min, x := cost[tmp], int64(1)
        for tmp != u {
            tmp, idx = stack[idx], idx-1
            if cost[tmp] < Min {
                Min, x = cost[tmp], 0
            }
            if cost[tmp] == Min {
                x++
            }
            instack[tmp] = 0
        }
        ans1 += Min
        ans2 = (ans2 * x) % 1000000007
    }
}

var (
    reader = bufio.NewReader(os.Stdin)
)

func main() {
    var n, m, a, b int
    Init()
    fmt.Fscan(reader, &n)
    for i := 1; i <= n; i++ {
        fmt.Fscan(reader, &cost[i])
    }
    fmt.Fscan(reader, &m)
    for i := 1; i <= m; i++ {
        fmt.Fscan(reader, &a, &b)
        addEdge(a, b)
    }
    for i := 1; i <= n; i++ {
        if dfn[i] == 0 {
            tarjan(i)
        }
    }
    fmt.Printf("%v %v\n", ans1, ans2)
}

package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"strconv"
	"time"
	"unicode/utf8"
)

// ******************************** CODE STARTS ********************************

var (
	G [][]int
	GR [][]int
	was []bool
	C []int
	comp int
	topsort []int
)

func dfs1(v int) {
	if was[v] {
		return
	}
	was[v] = true

	for i := 0; i < len(G[v]); i++ {
		dfs1(G[v][i])
	}

	topsort = append(topsort, v)
}

func dfs2(v int) {
	if was[v] {
		return
	}
	was[v] = true
	C[v] = comp

	for i := 0; i < len(GR[v]); i++ {
		dfs2(GR[v][i])
	}
}

func solve() {
	n := readInt()
	G = make([][]int, n)
	GR = make([][]int, n)
	C = make([]int, n)

	cost := make([]int, n)
	for i := 0; i < n; i++ {
		cost[i] = readInt()
	}

	m := readInt()
	for i := 0; i < m; i++ {
		a := readInt() - 1
		b := readInt() - 1
		G[a] = append(G[a], b)
		GR[b] = append(GR[b], a)
	}

	was = make([]bool, n)
	for i := 0; i < n; i++ {
		dfs1(i)
	}

	was = make([]bool, n)
	for i := n - 1; i >= 0; i-- {
		if !was[topsort[i]] {
			dfs2(topsort[i])
			comp++
		}
	}

	minCost := make([]int, comp)
	count := make([]int, comp)

	for i := 0; i < n; i++ {
		if count[C[i]] == 0 || minCost[C[i]] > cost[i] {
			count[C[i]] = 1
			minCost[C[i]] = cost[i]
		} else if minCost[C[i]] == cost[i] {
			count[C[i]]++
		}
	}

	mod := int64(1000 * 1000 * 1000 + 7)
	ways := int64(1)
	ans := int64(0)

	for i := 0; i < comp; i++ {
		ways *= int64(count[i])
		ways %= mod
		ans += int64(minCost[i])
	}

//	logln(cost)
//	logln(C)
//	logln(minCost)
//	logln(count)

	printInt64(ans)
	printString(" ")
	printInt64(ways)
	printLine()
}

// ********************************* CODE ENDS *********************************

// IO.

var (
	scanner *Scanner
	writer  *bufio.Writer
	logger  *log.Logger
)

func main() {
	local := flag.Bool("local", false, "Equals true, if run is local.")
	flag.Parse()

	var (
		input  *os.File
		output *os.File
	)

	if *local {
		startTime := time.Now()
		defer func() {
			println(fmt.Sprintf("Time: %.5fs", time.Since(startTime).Seconds()))
		}()
		input, _ = os.Open("/home/outside/coding/workspace/go/io/input.txt")
		output, _ = os.Create("/home/outside/coding/workspace/go/io/output.txt")
		logger = log.New(output, "log: ", 0)
	} else {
		input = os.Stdin
		output = os.Stdout
		// input, _ = os.Open("")
		// output, _ = os.Create("")
	}
	defer input.Close()
	defer output.Close()

	scanner = NewScanner(input)
	scanner.Split(bufio.ScanWords)

	writer = bufio.NewWriter(output)
	defer writer.Flush()

	solve()
}

// Read.

func readString() string {
	scanner.Scan()
	ans := scanner.Text()
	return ans
}

func readLine() string {
	scanner.Split(bufio.ScanLines)
	defer scanner.Split(bufio.ScanWords)
	return readString()
}

func readInt() int {
	ans, _ := strconv.ParseInt(readString(), 10, 0)
	return int(ans)
}

func readInt64() int64 {
	ans, _ := strconv.ParseInt(readString(), 10, 64)
	return ans
}

func readFloat64() float64 {
	ans, _ := strconv.ParseFloat(readString(), 64)
	return ans
}

// Write.

func printString(value string) {
	writer.WriteString(value)
}

func printLine() {
	printString("\n")
}

func printInt(value int) {
	printString(strconv.FormatInt(int64(value), 10))
}

func printInt64(value int64) {
	printString(strconv.FormatInt(value, 10))
}

func printFLoat64(value float64) {
	printString(strconv.FormatFloat(value, 'f', 20, 64))
}

// Log.

func logln(value ...interface{}) {
	writer.Flush()
	logger.Println(value...)
}
func logf(format string, value ...interface{}) {
	writer.Flush()
	logger.Printf(format, value...)
}

// Tuple

type Tuple struct {
	a, b int
}

func (p Tuple) Equals(key Key) bool {
	return p.a == key.(Tuple).a
}

func (p Tuple) Less(key Key) bool {
	return p.a < key.(Tuple).a
}

type TupleSlice []Tuple

func (p TupleSlice) Len() int {
	return len(p)
}

func (p TupleSlice) Less(j, i int) bool {
	return p[j].a < p[i].a
}

func (p TupleSlice) Swap(j, i int) {
	p[j], p[i] = p[i], p[j]
}

// Min, max, abs.

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

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

func absInt(a int) int {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

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

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

func absInt64(a int64) int64 {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

func maxFloat64(a, b float64) float64 {
	if a > b {
		return a
	} else {
		return b
	}
}

func minFloat64(a, b float64) float64 {
	if a < b {
		return a
	} else {
		return b
	}
}

func absFloat64(a float64) float64 {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

// Set Key interface implementations.

type Int int

func (p Int) Equals(key Key) bool {
	return int(p) == int(key.(Int))
}

func (p Int) Less(key Key) bool {
	return int(p) < int(key.(Int))
}

// Set.

type Key interface {
	Equals(key Key) bool
	Less(key Key) bool
}

type node struct {
	key   Key
	left  *node
	right *node
}

func newNode(key Key) *node {
	return &node{key, nil, nil}
}

type SplayTree struct {
	root *node
	tmp  *node
	len  int
}

func NewSplayTree() *SplayTree {
	return &SplayTree{nil, newNode(nil), 0}
}

func rotateLeft(x, p *node) {
	p.right = x.left
	x.left = p
}

func rotateRight(x, p *node) {
	p.left = x.right
	x.right = p
}

func (p *SplayTree) splay(x *node, key Key) *node {
	if x == nil {
		return nil
	}

	left := p.tmp
	right := p.tmp

	for {
		if key.Less(x.key) {
			y := x.left
			if y == nil {
				break
			}
			if key.Less(y.key) { // zig-zig
				rotateRight(y, x)
				x = y
				if x.left == nil {
					break
				}
			}
			// link right
			right.left = x
			right = x
			// move left
			x = x.left
		} else if x.key.Less(key) {
			y := x.right
			if y == nil {
				break
			}
			if y.key.Less(key) { // zig-zig
				rotateLeft(y, x)
				x = y
				if x.right == nil {
					break
				}
			}
			// link left
			left.right = x
			left = x
			// move right
			x = x.right
		} else {
			break
		}
	}

	left.right = x.left
	right.left = x.right
	x.left = p.tmp.right
	x.right = p.tmp.left

	return x
}

// left <= key < right
func (p *SplayTree) split(key Key) (left, right *node) {
	p.root = p.splay(p.root, key)
	if p.root.key.Equals(key) || p.root.key.Less(key) {
		right := p.root.right
		p.root.right = nil
		return p.root, right
	} else {
		left := p.root.left
		p.root.left = nil
		return left, p.root
	}
}

// keys from left tree must be less then keys from right tree
func (p *SplayTree) join(left, right *node) *node {
	if left == nil {
		return right
	} else if right == nil {
		return left
	}
	left = p.splay(left, right.key)
	left.right = right
	return left
}

type Set interface {
	Len() int
	Insert(key Key) error
	Find(key Key) bool
	Remove(key Key) error
}

func NewSet() Set {
	return Set(NewSplayTree())
}

func (p *SplayTree) Len() int {
	return p.len
}

func (p *SplayTree) Insert(key Key) error {
	if p.root == nil {
		p.root = newNode(key)
		p.len++
	} else {
		p.root = p.splay(p.root, key)
		if p.root.key.Equals(key) {
			return errors.New("Such key already exists")
		} else {
			left, right := p.split(key)
			p.root = newNode(key)
			p.root.left = left
			p.root.right = right
			p.len++
		}
	}
	return nil
}

func (p *SplayTree) Find(key Key) bool {
	if p.root == nil {
		return false
	}
	p.root = p.splay(p.root, key)
	return p.root.key.Equals(key)
}

func (p *SplayTree) Remove(key Key) error {
	p.root = p.splay(p.root, key)
	if p.root == nil || !p.root.key.Equals(key) {
		return errors.New("Such key doesn't exist")
	}
	p.root = p.join(p.split(key))
	return nil
}

// Copied scan.go
// Scanner provides a convenient interface for reading data such as
// a file of newline-delimited lines of text. Successive calls to
// the Scan method will step through the 'tokens' of a file, skipping
// the bytes between the tokens. The specification of a token is
// defined by a split function of type SplitFunc; the default split
// function breaks the input into lines with line termination stripped. Split
// functions are defined in this package for scanning a file into
// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
// client may instead provide a custom split function.
//
// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
// large to fit in the buffer. When a scan stops, the reader may have
// advanced arbitrarily far past the last token. Programs that need more
// control over error handling or large tokens, or must run sequential scans
// on a reader, should use bufio.Reader instead.
//
type Scanner struct {
        r            io.Reader // The reader provided by the client.
        split        SplitFunc // The function to split the tokens.
        maxTokenSize int       // Maximum size of a token; modified by tests.
        token        []byte    // Last token returned by split.
        buf          []byte    // Buffer used as argument to split.
        start        int       // First non-processed byte in buf.
        end          int       // End of data in buf.
        err          error     // Sticky error.
}

// SplitFunc is the signature of the split function used to tokenize the
// input. The arguments are an initial substring of the remaining unprocessed
// data and a flag, atEOF, that reports whether the Reader has no more data
// to give. The return values are the number of bytes to advance the input
// and the next token to return to the user, plus an error, if any. If the
// data does not yet hold a complete token, for instance if it has no newline
// while scanning lines, SplitFunc can return (0, nil, nil) to signal the
// Scanner to read more data into the slice and try again with a longer slice
// starting at the same point in the input.
//
// If the returned error is non-nil, scanning stops and the error
// is returned to the client.
//
// The function is never called with an empty data slice unless atEOF
// is true. If atEOF is true, however, data may be non-empty and,
// as always, holds unprocessed text.
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

// Errors returned by Scanner.
var (
        ErrTooLong         = errors.New("bufio.Scanner: token too long")
        ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
        ErrAdvanceTooFar   = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
)

const (
        // Maximum size used to buffer a token. The actual maximum token size
        // may be smaller as the buffer may need to include, for instance, a newline.
        MaxScanTokenSize = 1 << 30
)

// NewScanner returns a new Scanner to read from r.
// The split function defaults to ScanLines.
func NewScanner(r io.Reader) *Scanner {
        return &Scanner{
                r:            r,
                split:        ScanLines,
                maxTokenSize: MaxScanTokenSize,
                buf:          make([]byte, 4096), // Plausible starting size; needn't be large.
        }
}

// Err returns the first non-EOF error that was encountered by the Scanner.
func (s *Scanner) Err() error {
        if s.err == io.EOF {
                return nil
        }
        return s.err
}

// Bytes returns the most recent token generated by a call to Scan.
// The underlying array may point to data that will be overwritten
// by a subsequent call to Scan. It does no allocation.
func (s *Scanner) Bytes() []byte {
        return s.token
}

// Text returns the most recent token generated by a call to Scan
// as a newly allocated string holding its bytes.
func (s *Scanner) Text() string {
        return string(s.token)
}

// Scan advances the Scanner to the next token, which will then be
// available through the Bytes or Text method. It returns false when the
// scan stops, either by reaching the end of the input or an error.
// After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err
// will return nil.
func (s *Scanner) Scan() bool {
        // Loop until we have a token.
        for {
                // See if we can get a token with what we already have.
                if s.end > s.start {
                        advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)
                        if err != nil {
                                s.setErr(err)
                                return false
                        }
                        if !s.advance(advance) {
                                return false
                        }
                        s.token = token
                        if token != nil {
                                return true
                        }
                }
                // We cannot generate a token with what we are holding.
                // If we've already hit EOF or an I/O error, we are done.
                if s.err != nil {
                        // Shut it down.
                        s.start = 0
                        s.end = 0
                        return false
                }
                // Must read more data.
                // First, shift data to beginning of buffer if there's lots of empty space
                // or space is neded.
                if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) {
                        copy(s.buf, s.buf[s.start:s.end])
                        s.end -= s.start
                        s.start = 0
                }
                // Is the buffer full? If so, resize.
                if s.end == len(s.buf) {
                        if len(s.buf) >= s.maxTokenSize {
                                s.setErr(ErrTooLong)
                                return false
                        }
                        newSize := len(s.buf) * 2
                        if newSize > s.maxTokenSize {
                                newSize = s.maxTokenSize
                        }
                        newBuf := make([]byte, newSize)
                        copy(newBuf, s.buf[s.start:s.end])
                        s.buf = newBuf
                        s.end -= s.start
                        s.start = 0
                        continue
                }
                // Finally we can read some input. Make sure we don't get stuck with
                // a misbehaving Reader. Officially we don't need to do this, but let's
                // be extra careful: Scanner is for safe, simple jobs.
                for loop := 0; ; {
                        n, err := s.r.Read(s.buf[s.end:len(s.buf)])
                        s.end += n
                        if err != nil {
                                s.setErr(err)
                                break
                        }
                        if n > 0 {
                                break
                        }
                        loop++
                        if loop > 100 {
                                s.setErr(io.ErrNoProgress)
                                break
                        }
                }
        }
}

// advance consumes n bytes of the buffer. It reports whether the advance was legal.
func (s *Scanner) advance(n int) bool {
        if n < 0 {
                s.setErr(ErrNegativeAdvance)
                return false
        }
        if n > s.end-s.start {
                s.setErr(ErrAdvanceTooFar)
                return false
        }
        s.start += n
        return true
}

// setErr records the first error encountered.
func (s *Scanner) setErr(err error) {
        if s.err == nil || s.err == io.EOF {
                s.err = err
        }
}

// Split sets the split function for the Scanner. If called, it must be
// called before Scan. The default split function is ScanLines.
func (s *Scanner) Split(split SplitFunc) {
        s.split = split
}

// Split functions

// ScanBytes is a split function for a Scanner that returns each byte as a token.
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }
        return 1, data[0:1], nil
}

var errorRune = []byte(string(utf8.RuneError))

// ScanRunes is a split function for a Scanner that returns each
// UTF-8-encoded rune as a token. The sequence of runes returned is
// equivalent to that from a range loop over the input as a string, which
// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
// Because of the Scan interface, this makes it impossible for the client to
// distinguish correctly encoded replacement runes from encoding errors.
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }

        // Fast path 1: ASCII.
        if data[0] < utf8.RuneSelf {
                return 1, data[0:1], nil
        }

        // Fast path 2: Correct UTF-8 decode without error.
        _, width := utf8.DecodeRune(data)
        if width > 1 {
                // It's a valid encoding. Width cannot be one for a correctly encoded
                // non-ASCII rune.
                return width, data[0:width], nil
        }

        // We know it's an error: we have width==1 and implicitly r==utf8.RuneError.
        // Is the error because there wasn't a full rune to be decoded?
        // FullRune distinguishes correctly between erroneous and incomplete encodings.
        if !atEOF && !utf8.FullRune(data) {
                // Incomplete; get more bytes.
                return 0, nil, nil
        }

        // We have a real UTF-8 encoding error. Return a properly encoded error rune
        // but advance only one byte. This matches the behavior of a range loop over
        // an incorrectly encoded string.
        return 1, errorRune, nil
}

// dropCR drops a terminal \r from the data.
func dropCR(data []byte) []byte {
        if len(data) > 0 && data[len(data)-1] == '\r' {
                return data[0 : len(data)-1]
        }
        return data
}

// ScanLines is a split function for a Scanner that returns each line of
// text, stripped of any trailing end-of-line marker. The returned line may
// be empty. The end-of-line marker is one optional carriage return followed
// by one mandatory newline. In regular expression notation, it is `\r?\n`.
// The last non-empty line of input will be returned even if it has no
// newline.
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }
        if i := bytes.IndexByte(data, '\n'); i >= 0 {
                // We have a full newline-terminated line.
                return i + 1, dropCR(data[0:i]), nil
        }
        // If we're at EOF, we have a final, non-terminated line. Return it.
        if atEOF {
                return len(data), dropCR(data), nil
        }
        // Request more data.
        return 0, nil, nil
}

// isSpace reports whether the character is a Unicode white space character.
// We avoid dependency on the unicode package, but check validity of the implementation
// in the tests.
func isSpace(r rune) bool {
        if r <= '\u00FF' {
                // Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs.
                switch r {
                case ' ', '\t', '\n', '\v', '\f', '\r':
                        return true
                case '\u0085', '\u00A0':
                        return true
                }
                return false
        }
        // High-valued ones.
        if '\u2000' <= r && r <= '\u200a' {
                return true
        }
        switch r {
        case '\u1680', '\u180e', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000':
                return true
        }
        return false
}

// ScanWords is a split function for a Scanner that returns each
// space-separated word of text, with surrounding spaces deleted. It will
// never return an empty string. The definition of space is set by
// unicode.IsSpace.
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
        // Skip leading spaces.
        start := 0
        for width := 0; start < len(data); start += width {
                var r rune
                r, width = utf8.DecodeRune(data[start:])
                if !isSpace(r) {
                        break
                }
        }
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }
        // Scan until space, marking end of word.
        for width, i := 0, start; i < len(data); i += width {
                var r rune
                r, width = utf8.DecodeRune(data[i:])
                if isSpace(r) {
                        return i + width, data[start:i], nil
                }
        }
        // If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
        if atEOF && len(data) > start {
                return len(data), data[start:], nil
        }
        // Request more data.
        return 0, nil, nil
}

//package main
//
//import (
//	"bufio"
//	"fmt"
//	"os"
//)
//
//// Edge is a intermediate representation of edge on DirectedGraph
//type Edge struct {
//	From  Vertex
//	To    Vertex
//	Value Rel // raw value of edge
//}
//type Vertex struct {
//	Value interface{}
//}
//var cost []int64
//var n int
//type Rel string
//type DirectedGraph struct {
//	Outs map[Vertex]map[Vertex][]Rel
//	Ins  map[Vertex][]Vertex
//}
//
//// Vertices returns the set of all vertices in graph
//func (g *DirectedGraph) Vertices() []Vertex {
//	vertices := []Vertex{}
//
//	for key := range g.Outs {
//		vertices = append(vertices, key)
//	}
//	return vertices
///*	vertices := []Vertex{}
//	haveIn := make(map[Vertex]bool)
//
//	for key := range g.Outs {
//		vertices = append(vertices, key)
//		haveIn[key] = true
//		for vertex, _ := range g.Outs[key] {
//			_, ok := haveIn[vertex]
//			if ok == false {
//				vertices = append(vertices, vertex)
//				fmt.Println(vertex, "   !")
//			}
//		}
//	}
//	return vertices*/
//}
//
//// In returns inbound vertices to v in graph g
//func (g *DirectedGraph) In(v Vertex) []Vertex {
//	_, ok := g.Ins[v]
//	if !ok {
//		return []Vertex{}
//	} else {
//		return g.Ins[v]
//	}
//}
//
//// Out returns outbound vertices from v in graph g
//func (g *DirectedGraph) Out(v Vertex) []Vertex {
//	_, ok := g.Outs[v]
//	if !ok {
//		return []Vertex{}
//	}
//
//	vertices := []Vertex{}
//
//	for key := range g.Outs[v] {
//		vertices = append(vertices, key)
//	}
//	return vertices
//}
//
//// Edges returns the edge between two vertices
//func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
//	_, oka := g.Outs[a]
//	_, okb := g.Ins[b]
//	if !oka || !okb {
//		return nil
//	}
//
//	_, ok := g.Outs[a][b]
//	if !ok {
//		return nil
//	}
//
//	edges := []Edge{}
//	for _, rel := range g.Outs[a][b] {
//		edges = append(edges, Edge{
//			From:  a,
//			To:    b,
//			Value: rel,
//		})
//	}
//	return edges
//}
//
//// Link links two vertices relationship
//func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
//	_, ok := g.Outs[v]
//	if !ok {
//		g.Outs[v] = make(map[Vertex][]Rel)
//	}
//	_, ok = g.Outs[succ]
//	if !ok {
//		g.Outs[succ] = make(map[Vertex][]Rel)
//	}
//
//	_, ok = g.Ins[v]
//	if !ok {
//		g.Ins[v] = []Vertex{}
//	}
//	_, ok = g.Ins[succ]
//	if !ok {
//		g.Ins[succ] = []Vertex{}
//	}
//
//	haveRel := false
//	for _, item := range g.Outs[v][succ] {
//		if item == rel {
//			haveRel = true
//			break
//		}
//	}
//	if haveRel == false {
//		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
//	}
//
//	/*if n<90000 {
//		haveV := false
//		for _, item := range g.Ins[succ] {
//			if item == v {
//				haveV = true
//				break
//			}
//		}
//		if haveV == false {
//			g.Ins[succ] = append(g.Ins[succ], v)
//		}
//	}*/
//
//	if _, ok:= g.Outs[v][succ] ; ok ==false{
//		g.Ins[succ] = append(g.Ins[succ], v)
//	}
//}
//
//// LinkToAll links x to all ys
//func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
//	for _, y := range ys {
//		g.Link(x, y, rel)
//	}
//}
//
//// LinkAllTo links all xs to y
//func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
//	for _, x := range xs {
//		g.Link(x, y, rel)
//	}
//}
//
//func (g *DirectedGraph) UnLink(a, b Vertex) {
//	delete(g.Outs[a], b)
//	/*if len(g.Outs[a]) == 0 {
//		delete(g.Outs, a)
//	}*/
//
//	for id , vertex := range g.Ins[b] {
//		if vertex == a {
//			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
//			break
//		}
//	}
//	/*if len(g.Ins[b]) == 0 {
//		delete(g.Ins, b)
//	}*/
//}
//
//// Fork implements `forked` semantics on DirectedGraph
//func (g *DirectedGraph) Fork() *DirectedGraph {
//	return g
//	//return deepcopy.Copy(g).(*DirectedGraph)
//	//panic("impl me")
//}
//// IntersectionRel returns the union of res1 and res2
//func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
//	rel := []Rel{}
//	for _, rel1 := range rels1 {
//		both := false
//		for _, rel2 := range rels2{
//			if rel1 == rel2 {
//				both = true
//				break
//			}
//		}
//		if both == true {
//			rel = append(rel, rel1)
//		}
//	}
//	return rel
//}
//
//// ProjectRelationship filters a graph to just those edges with the given relationship
//func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
//	fg := g.Fork()
//
//	vertices := fg.Vertices()
//	for _, x := range vertices {
//		_, ok := g.Outs[x]
//		if ok == true {
//			for y, _:= range g.Outs[x] {
//				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
//				fg.UnLink(x, y)
//				for _, item := range rels {
//					fg.Link(x, y, item)
//				}
//			}
//		}
//	}
//
//	return fg
//}
//
//// FilterRelationships filters a graph g to just those edges which intersect with the given set of
////  relationships
//func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
//	fg := g.Fork()
//
//	vertices := fg.Vertices()
//	for _, x := range vertices {
//		_, ok := g.Outs[x]
//		if ok == true {
//			for y, _:= range g.Outs[x] {
//				rels := IntersectionRel(g.Outs[x][y], rels)
//				fg.UnLink(x, y)
//				for _, item := range rels {
//					fg.Link(x, y, item)
//				}
//			}
//		}
//	}
//
//	return fg
//}
//
//// BfsOut searches from a vertices set, returns all vertices searchable
//// search to downstream vertices from `out` edges
//func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
//	queue := initV
//	V := []Vertex{}
//	haveVisited := make(map[Vertex]bool)
//	for _, vertex := range initV {
//		haveVisited[vertex] = true
//		V = append(V, vertex)
//	}
//
//	for len(queue) > 0 {
//		cur := queue[0]
//		if haveVisited[cur] == false {
//			haveVisited[cur] = true
//			V = append(V, cur)
//		}
//		queue = queue[1:]
//
//		for next, _ := range g.Outs[cur] {
//			if haveVisited[next] == true {
//				continue
//			}
//			queue = append(queue, next)
//		}
//	}
//	return V
//}
//
//// BfsIn searches from a vertices set, returns all vertices searchable
//// search to upstream vertices from `in` edges
//func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
//	queue := initV
//	V := []Vertex{}
//	haveVisited := make(map[Vertex]bool)
//	for _, vertex := range initV {
//		haveVisited[vertex] = true
//		V = append(V, vertex)
//	}
//
//	for len(queue) > 0 {
//		cur := queue[0]
//		if haveVisited[cur] == false {
//			haveVisited[cur] = true
//			V = append(V, cur)
//		}
//		queue = queue[1:]
//
//		for _, next := range g.Ins[cur] {
//			if haveVisited[next] == true {
//				continue
//			}
//			queue = append(queue, next)
//		}
//	}
//	return V
//}
//
//// Bfs searches from a vertices set, returns all vertices searchable
//// out = true means search to downstream vertices from `out` edges
//// out = false means search to upstream vertices from `in` edges
//func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
//	if out == true {
//		return g.BfsOut(initV)
//	} else {
//		return g.BfsIn(initV)
//	}
//}
//
//// SCC indexes all vertices of a strongly connected component
//type SCC struct {
//	Vertices []Vertex
//}
//
//// StronglyConnectedComponents finds all strongly connected components
//func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
//	//dfn := make(map[Vertex]int)
//	//low := make(map[Vertex]int)
//	dfn := make([]int, n+5)
//	low := make([]int, n+5)
//	belong := make([]int, n+5)
//	in := make([]bool, n+5)
//
//
//	cnt := 0
//	//belong := make(map[Vertex]int)
//	//in := make(map[Vertex]bool)
//	tag := make(map[Vertex]map[Vertex]bool)
//	s2 := []Vertex{}
//	//scc := []SCC{}
//	//vertices := g.Vertices()
//	index := 0
//	for v:=1 ; v<=n; v++ {
//		if dfn[v] == 0 {
//			s1 := []Vertex{{v}}
//			//index := 0
//			for len(s1) > 0 {
//				x := s1[len(s1)-1]
//				s1 = s1[:len(s1)-1]
//				if dfn[x.Value.(int)] == 0 {
//					index = index + 1
//					dfn[x.Value.(int)] = index
//					low[x.Value.(int)] = index
//					s2 = append(s2, x)
//					in[x.Value.(int)] = true;
//				}
//				finish := true
//				for next, _ := range g.Outs[x] {
//					//fmt.Println("************")
//					if dfn[next.Value.(int)] == 0 {
//						s1 = append(s1, x)
//						s1 = append(s1, next)
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						tag[x][next] = true
//						finish = false
//						break
//					} else {
//						if in[next.Value.(int)] == true {
//							if low[x.Value.(int)] > dfn[next.Value.(int)] {
//								low[x.Value.(int)] = dfn[next.Value.(int)]
//							}
//						}
//					}
//				}
//				if finish == true {
//					//fmt.Println("??????????")
//					for next, _ := range g.Outs[x] {
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						if tag[x][next] == true {
//							if low[x.Value.(int)] > low[next.Value.(int)] {
//								low[x.Value.(int)] = low[next.Value.(int)]
//							}
//						}
//					}
//					//fmt.Println("!!!!!!!!!!!!")
//					if low[x.Value.(int)] == dfn[x.Value.(int)] {
//						var t Vertex
//						cnt = cnt + 1
//						for {
//							t = s2[len(s2)-1]
//							s2 = s2[:len(s2)-1]
//							in[t.Value.(int)] = false
//							belong[t.Value.(int)] = cnt;
//							if t == x {
//								break
//							}
//						}
//					}
//				}
//			}
//		}
//	}
//	//fmt.Println(cnt, "!!!!!")
//
//	minc:=make([]int64, n+5)
//	nway:=make([]int64, n+5)
//
//	var sum,sumn int64
//	sum=0
//	sumn=1
//
//	/*for i := 1; i <= cnt; i++ {
//		ts := SCC{
//			Vertices: []Vertex{},
//		}
//		minc[i]=2147483647
//		for _, v := range vertices {
//			if belong[v] == i {
//				//ts.Vertices = append(ts.Vertices, v)
//				if cost[v.Value.(int)]<minc[i] {
//					minc[i]=cost[v.Value.(int)];
//					nway[i]=1;
//				} else {
//					if cost[v.Value.(int)] == minc[i] {
//						nway[i]++;
//					}
//				}
//			}
//		}
//		//scc = append(scc, ts)
//		sum+=minc[i];
//		sumn=(sumn*nway[i])%1000000007;
//	}*/
//	for i := 1; i <= cnt; i++ {
//		minc[i]=2147483647
//	}
//	for v :=1; v<=n; v++ {
//		id := belong[v]
//		if cost[v]<minc[id] {
//			minc[id]=cost[v];
//			nway[id]=1;
//		} else {
//			if cost[v] == minc[id] {
//				nway[id]++;
//			}
//		}
//	}
//	for i := 1; i <= cnt; i++ {
//		sum+=minc[i];
//		sumn=(sumn*nway[i])%1000000007;
//	}
//
//	fmt.Println(sum,sumn)
//
//	return nil
//}
//
//// MapVertices takes a function of vertices, returns graph with all
////  vertices mapped via f
//func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
//	//fmt.Println(f("consistent-view"))
//	fg := NewDirectedGraph()
//
//	vertices := g.Vertices()
//	for _, x := range vertices {
//		_, ok := g.Outs[x]
//		if ok == true {
//			for y, _:= range g.Outs[x] {
//				rels := g.Outs[x][y]
//				for _, item := range rels {
//					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
//				}
//			}
//		}
//	}
//
//	return fg
//}
//
//var canonicalModelNames = map[string]string{
//	"consistent-view":         "PL-2+",
//	"conflict-serializable":   "PL-3",
//	"cursor-stability":        "PL-CS",
//	"forward-consistent-view": "PL-FCV",
//	"monotonic-snapshot-read": "PL-MSR",
//	"monotonic-view":          "PL-2L",
//	"read-committed":          "PL-2",
//	"read-uncommitted":        "PL-1",
//	"repeatable-read":         "PL-2.99",
//	"serializable":            "PL-3",
//	"snapshot-isolation":      "PL-SI",
//	"strict-serializable":     "PL-SS",
//	"update-serializable":     "PL-3U",
//	"0": "A",
//	"1": "B",
//	"2": "C",
//}
//
//// canonicalModelName can be applied to DirectedGraph.MapVertices
//func canonicalModelName(name interface{}) interface{} {
//	if cname, ok := canonicalModelNames[name.(string)]; ok {
//		return cname
//	}
//	return name
//}
//
//// NewDirectedGraph returns a empty DirectedGraph
//func NewDirectedGraph() *DirectedGraph {
//	var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	return &g
//}
//
//// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
////  rewritten Graph, and a vector of the original vertices for reconstruction.
//// That means if we apply MapVertices to dg with remap, it can recover to g again
//func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
//	dg := NewDirectedGraph()
//	ref := make(map[Vertex]int)
//	numberToVertices := make(map[interface{}]interface{})
//	vertices := g.Vertices()
//
//	for id, v := range vertices {
//		ref[v] = id
//		numberToVertices[id] = v.Value
//	}
//
//	for _, x := range vertices {
//		for y, rels := range g.Outs[x] {
//			for _, rel := range rels{
//				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
//			}
//		}
//	}
//
//	return dg, func(number interface{}) interface{} {
//		return numberToVertices[number]
//	}
//}
//
//func (g *DirectedGraph) scctest() [][]int {
//	dfn := make(map[Vertex]int)
//	low := make(map[Vertex]int)
//	cnt := 0
//	belong := make(map[Vertex]int)
//	in := make(map[Vertex]bool)
//	tag := make(map[Vertex]map[Vertex]bool)
//	s2 := []Vertex{}
//	vertices := g.Vertices()
//	ans := [][]int{}
//	father := make(map[Vertex]Vertex)
//	vv := Vertex{-1}
//	index := 0
//	for _, v := range vertices {
//		if dfn[v] == 0 {
//			s1 := []Vertex{v}
//			father[v] = vv
//			for len(s1) > 0 {
//				x := s1[len(s1)-1]
//				s1 = s1[:len(s1)-1]
//				if dfn[x] == 0 {
//					index = index + 1
//					dfn[x] = index
//					low[x] = index
//					s2 = append(s2, x)
//					in[x] = true;
//				}
//				finish := true
//				for next, _ := range g.Outs[x] {
//					if dfn[next] == 0 {
//						s1 = append(s1, x)
//						s1 = append(s1, next)
//						father[next]=x
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						tag[x][next] = true
//						finish = false
//						break
//					} else {
//						if in[next] == true {
//							if low[x] > dfn[next] {
//								low[x] = dfn[next]
//								//fmt.Println("!!!!!!!")
//								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
//							}
//						}
//					}
//				}
//				if finish == true {
//					for next, _ := range g.Outs[x] {
//						_, ok := tag[x]
//						if !ok {
//							tag[x] = make(map[Vertex]bool)
//						}
//						if tag[x][next] == true {
//							if low[x] > low[next] {
//								low[x] = low[next]
//								//fmt.Println("!!!!!!")
//								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
//							}
//						}
//					}
//					if low[x] == dfn[x] {
//						var t Vertex
//						cnt = cnt + 1
//						for {
//							t = s2[len(s2)-1]
//							s2 = s2[:len(s2)-1]
//							in[t] = false
//							belong[t] = cnt;
//							if t == x {
//								break
//							}
//						}
//					}
//				}
//			}
//		}
//	}
//	for i := 1; i <= cnt; i++ {
//		ts := SCC{
//			Vertices: []Vertex{},
//		}
//		for _, v := range vertices {
//			if belong[v] == i {
//				ts.Vertices = append(ts.Vertices, v)
//			}
//		}
//		//fmt.Println(ts)
//	}
//
//	/*for _, x := range vertices{
//		for y, _ := range g.Outs[x] {
//			if low[x] != low[y] {
//				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
//			}
//		}
//	}*/
//	for _, i:= range vertices{
//		v:= father[i]
//		//fmt.Println(i , "  " ,v )
//		if v != vv {
//			fmt.Println(low[i]," ",dfn[v])
//			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
//		}
//	}
//
//	return ans
//}
//
//
//func criticalConnections(n int, connections [][]int) [][]int {
//	g := NewDirectedGraph()
//	for _, b := range connections{
//		g.Link(Vertex{b[0]},Vertex{b[1]},"")
//		g.Link(Vertex{b[1]},Vertex{b[0]},"")
//	}
//
//	return g.scctest()
//}
//
//func main () {
//	/*var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	g.Link(Vertex{0},Vertex{1},"")
//	g.Link(Vertex{1},Vertex{2},"")
//	g.Link(Vertex{2},Vertex{3},"")
//	g.Link(Vertex{3},Vertex{2},"")
//	g.Link(Vertex{3},Vertex{7},"")
//	g.Link(Vertex{7},Vertex{3},"")
//	g.Link(Vertex{2},Vertex{6},"")
//	g.Link(Vertex{7},Vertex{6},"")
//	g.Link(Vertex{5},Vertex{6},"")
//	g.Link(Vertex{6},Vertex{5},"")
//	g.Link(Vertex{1},Vertex{5},"")
//	g.Link(Vertex{4},Vertex{5},"")
//	g.Link(Vertex{4},Vertex{0},"")
//	g.Link(Vertex{1},Vertex{4},"")
//	// init done ==================================
//	// scc ========================================
//	scc := g.StronglyConnectedComponents()
//	fmt.Println(len(scc))
//	fmt.Println(scc)*/
//	//(5, 6) (7, 3, 2) (4, 1, 0)
//	// scc done ===================================
//
//
//	/*var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	g.Link(Vertex{"0"},Vertex{"1"},"aa")
//	g.Link(Vertex{"0"},Vertex{"1"},"bb")
//	//g.Link(Vertex{"0"},Vertex{"2"},"")
//	g.Link(Vertex{"1"},Vertex{"2"},"cc")
//	g.Link(Vertex{"2"},Vertex{"3"},"")
//
////	g.UnLink(Vertex{"0"},Vertex{"1"})
//	fmt.Println(g.Ins)
//	fmt.Println(g.Outs)
//	fmt.Println(g.Vertices())
//	xxx := g.MapVertices(canonicalModelName)
//	fmt.Println(xxx.Ins)
//	fmt.Println(xxx.Outs)
//	//fmt.Println("!!!!!!!")
//	fmt.Println(xxx.Vertices())*/
//
//	/*var g DirectedGraph
//	g.Ins = make(map[Vertex][]Vertex)
//	g.Outs = make(map[Vertex]map[Vertex][]Rel)
//	g.Link(Vertex{"A"},Vertex{"B"},"aa")
//	g.Link(Vertex{"A"},Vertex{"B"},"bb")
//	//g.Link(Vertex{"0"},Vertex{"2"},"")
//	g.Link(Vertex{"B"},Vertex{"C"},"cc")
//	g.Link(Vertex{"C"},Vertex{"D"},"")
//	dg, remap := g.RenumberGraph()
//	fmt.Println(g.Ins)
//	fmt.Println(g.Outs)
//	//fmt.Println(dg.Ins)
//	//fmt.Println(dg.Outs)
//
//	xx := dg.MapVertices(remap)
//	fmt.Println(xx.Ins)
//	fmt.Println(xx.Outs)*/
//
//
//	/*var connections [][]int
//	connections = append (connections, []int{0,1})
//	connections = append (connections, []int{1,2})
//	connections = append (connections, []int{2,0})
//	connections = append (connections, []int{1,3})
//	fmt.Println(criticalConnections(4,connections))*/
//	var m int
//	in := bufio.NewReader(os.Stdin)
//
//	fmt.Fscan(in, &n)
//	//fmt.Scan(&n)
//	cost = make([]int64, n+5)
//	g := NewDirectedGraph()
//	for i:=1 ; i<=n; i++ {
//		fmt.Fscan(in, &cost[i])
//
//		_, ok := g.Outs[Vertex{i}]
//		if !ok {
//			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
//		}
//		_, ok = g.Ins[Vertex{i}]
//		if !ok {
//			g.Ins[Vertex{i}] = []Vertex{}
//		}
//
//	}
//	fmt.Fscan(in, &m)
//	var a,b int
//	for i:=1 ; i<=m; i++ {
//		fmt.Fscan(in, &a)
//		fmt.Fscan(in, &b)
//		g.Link(Vertex{a}, Vertex{b}, "")
//	}
//	g.StronglyConnectedComponents()
//}
package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
	/*  vertices := []Vertex{}
	    haveIn := make(map[Vertex]bool)

	    for key := range g.Outs {
	        vertices = append(vertices, key)
	        haveIn[key] = true
	        for vertex, _ := range g.Outs[key] {
	            _, ok := haveIn[vertex]
	            if ok == false {
	                vertices = append(vertices, vertex)
	                fmt.Println(vertex, "   !")
	            }
	        }
	    }
	    return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}

	/*if n<90000 {
	    haveV := false
	    for _, item := range g.Ins[succ] {
	        if item == v {
	            haveV = true
	            break
	        }
	    }
	    if haveV == false {
	        g.Ins[succ] = append(g.Ins[succ], v)
	    }
	}*/

	if _, ok:= g.Outs[v][succ] ; ok ==false{
		g.Ins[succ] = append(g.Ins[succ], v)
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
	    delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
	    delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	//index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make(map[int]int64)
	nway:=make(map[int]int64)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	scc := make([]SCC, cnt)
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}

	for _, v := range vertices {
		/*if belong[v] == i {
			ts.Vertices = append(ts.Vertices, v)
			if cost[v.Value.(int)]<minc[i] {
				minc[i]=cost[v.Value.(int)];
				nway[i]=1;
			} else {
				if cost[v.Value.(int)] == minc[i] {
					nway[i]++;
				}
			}
		}*/
		id := belong[v]
		scc[id-1].Vertices = append(scc[id-1].Vertices, v)
		if cost[v.Value.(int)]<minc[id] {
			minc[id]=cost[v.Value.(int)];
			nway[id]=1;
		} else {
			if cost[v.Value.(int)] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
				sum+=minc[i];
				sumn=(sumn*nway[i])%1000000007;
			}
	fmt.Println(sum,sumn)

	return scc
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
	    for y, _ := range g.Outs[x] {
	        if low[x] != low[y] {
	            ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
	        }
	    }
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	  g.Ins = make(map[Vertex][]Vertex)
	  g.Outs = make(map[Vertex]map[Vertex][]Rel)
	  g.Link(Vertex{0},Vertex{1},"")
	  g.Link(Vertex{1},Vertex{2},"")
	  g.Link(Vertex{2},Vertex{3},"")
	  g.Link(Vertex{3},Vertex{2},"")
	  g.Link(Vertex{3},Vertex{7},"")
	  g.Link(Vertex{7},Vertex{3},"")
	  g.Link(Vertex{2},Vertex{6},"")
	  g.Link(Vertex{7},Vertex{6},"")
	  g.Link(Vertex{5},Vertex{6},"")
	  g.Link(Vertex{6},Vertex{5},"")
	  g.Link(Vertex{1},Vertex{5},"")
	  g.Link(Vertex{4},Vertex{5},"")
	  g.Link(Vertex{4},Vertex{0},"")
	  g.Link(Vertex{1},Vertex{4},"")
	  // init done ==================================
	  // scc ========================================
	  scc := g.StronglyConnectedComponents()
	  fmt.Println(len(scc))
	  fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	    g.Ins = make(map[Vertex][]Vertex)
	    g.Outs = make(map[Vertex]map[Vertex][]Rel)
	    g.Link(Vertex{"0"},Vertex{"1"},"aa")
	    g.Link(Vertex{"0"},Vertex{"1"},"bb")
	    //g.Link(Vertex{"0"},Vertex{"2"},"")
	    g.Link(Vertex{"1"},Vertex{"2"},"cc")
	    g.Link(Vertex{"2"},Vertex{"3"},"")

	//  g.UnLink(Vertex{"0"},Vertex{"1"})
	    fmt.Println(g.Ins)
	    fmt.Println(g.Outs)
	    fmt.Println(g.Vertices())
	    xxx := g.MapVertices(canonicalModelName)
	    fmt.Println(xxx.Ins)
	    fmt.Println(xxx.Outs)
	    //fmt.Println("!!!!!!!")
	    fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	  g.Ins = make(map[Vertex][]Vertex)
	  g.Outs = make(map[Vertex]map[Vertex][]Rel)
	  g.Link(Vertex{"A"},Vertex{"B"},"aa")
	  g.Link(Vertex{"A"},Vertex{"B"},"bb")
	  //g.Link(Vertex{"0"},Vertex{"2"},"")
	  g.Link(Vertex{"B"},Vertex{"C"},"cc")
	  g.Link(Vertex{"C"},Vertex{"D"},"")
	  dg, remap := g.RenumberGraph()
	  fmt.Println(g.Ins)
	  fmt.Println(g.Outs)
	  //fmt.Println(dg.Ins)
	  //fmt.Println(dg.Outs)

	  xx := dg.MapVertices(remap)
	  fmt.Println(xx.Ins)
	  fmt.Println(xx.Outs)*/

	/*var connections [][]int
	  connections = append (connections, []int{0,1})
	  connections = append (connections, []int{1,2})
	  connections = append (connections, []int{2,0})
	  connections = append (connections, []int{1,3})
	  fmt.Println(criticalConnections(4,connections))*/
	var n int
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		g.Link(Vertex{a}, Vertex{b}, "")
	}
	g.StronglyConnectedComponents()
}

package main

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

type Graph struct {
	nodes []int64
	edges map[int64][]int64
}

func (g *Graph) addNode(n int64) {
	g.nodes = append(g.nodes, n)
}

func (g *Graph) addEdge(n1, n2 int64) {
	if g.edges == nil {
		g.edges = make(map[int64][]int64)
	}
	if g.edges[n1] == nil {
		g.edges[n1] = make([]int64, 0)
	}
	g.edges[n1] = append(g.edges[n1], n2)
}

func (g *Graph) fillInOrder(node int64, stack *[]int64, visited []bool) {
	visited[node] = true
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.fillInOrder(v, stack, visited)
		}
	}
	*stack = append(*stack, node)
}

func (g *Graph) dfs(node int64, visited []bool, min *int64, duplicate *int64) {
	visited[node] = true
	if prices[node] < *min {
		*min = prices[node]
		*duplicate = 1
	} else if prices[node] == *min {
		*duplicate += 1
	}
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.dfs(v, visited, min, duplicate)
		}
	}
}

func (g *Graph) findSCC() {
	visited := make([]bool, len(g.nodes)+1)
	stack := make([]int64, 0)
	for _, i := range g.nodes {
		if !visited[i] {
			g.fillInOrder(i, &stack, visited)
		}
	}

	newEdges := make(map[int64][]int64)
	for k, s := range g.edges {
		for _, v := range s {
			if newEdges[v] == nil {
				newEdges[v] = make([]int64, 0)
			}
			newEdges[v] = append(newEdges[v], k)
		}
	}
	g.edges = newEdges

	visited = make([]bool, len(g.nodes)+1)
	var minCost int64 = 0
	var ways int64 = 1
	for len(stack) != 0 {
		top := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		var min int64 = 1000000001
		var duplicate int64 = 1
		if !visited[top] {
			g.dfs(top, visited, &min, &duplicate)
			minCost += min
			ways *= duplicate
		}
	}
	fmt.Println(minCost, ways%1000000007)
}

var g Graph
var prices []int64

func main() {
	var n, m, a, b, tmp int64
	reader := bufio.NewReader(os.Stdin)
	fmt.Fscan(reader, &n)
	var i int64 = 0
	for i = 1; i <= n; i += 1 {
		fmt.Fscan(reader, &tmp)
		prices = append(prices, tmp)
		g.addNode(i)
	}
	prices = append([]int64{0}, prices...)
	fmt.Fscan(reader, &m)
	for i = 1; i <= m; i += 1 {
		fmt.Fscan(reader, &a, &b)
		g.addEdge(a, b)
	}
	g.findSCC()
}

package main

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

type Graph struct {
	nodes []int
	edges map[int][]int
}

func (g *Graph) addNode(n int) {
	g.nodes = append(g.nodes, n)
}

func (g *Graph) addEdge(n1, n2 int) {
	if g.edges == nil {
		g.edges = make(map[int][]int)
	}
	if g.edges[n1] == nil {
		g.edges[n1] = make([]int, 0)
	}
	g.edges[n1] = append(g.edges[n1], n2)
}

func (g *Graph) fillInOrder(node int, stack *[]int, visited []bool) {
	visited[node] = true
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.fillInOrder(v, stack, visited)
		}
	}
	*stack = append(*stack, node)
}

func (g *Graph) dfs(node int, visited []bool, min *int, duplicate *int) {
	visited[node] = true
	if prices[node] < *min {
		*min = prices[node]
		*duplicate = 1
	} else if prices[node] == *min {
		*duplicate += 1
	}
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.dfs(v, visited, min, duplicate)
		}
	}
}

func (g *Graph) findSCC() {
	visited := make([]bool, len(g.nodes)+1)
	stack := make([]int, 0)
	for _, i := range g.nodes {
		if !visited[i] {
			g.fillInOrder(i, &stack, visited)
		}
	}

	newEdges := make(map[int][]int)
	for k, s := range g.edges {
		for _, v := range s {
			if newEdges[v] == nil {
				newEdges[v] = make([]int, 0)
			}
			newEdges[v] = append(newEdges[v], k)
		}
	}
	oldEdges := g.edges
	g.edges = newEdges

	visited = make([]bool, len(g.nodes)+1)
	count := 0
	minCost := 0
	ways := 1
	for len(stack) != 0 {
		top := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		min := 1000000001
		duplicate := 1
		if !visited[top] {
			count += 1
			g.dfs(top, visited, &min, &duplicate)
			minCost += min
			ways *= duplicate
		}
	}
	fmt.Println(minCost%1000000007, ways)

	g.edges = oldEdges
}

func numbers(s string) []int {
	var n []int
	for _, f := range strings.Split(s, " ") {
		i, err := strconv.Atoi(strings.TrimSuffix(f, "\n"))
		if err == nil {
			n = append(n, i)
		}
	}
	return n
}

var g Graph
var prices []int

func main() {
	reader := bufio.NewReader(os.Stdin)
	firstLine, _ := reader.ReadString('\n')
	n, _ := strconv.Atoi(strings.TrimSuffix(firstLine, "\n"))
	priceLine, _ := reader.ReadString('\n')
	prices = numbers(priceLine)
	prices = append([]int{0}, prices...)
	for i := 1; i <= n; i += 1 {
		g.addNode(i)
	}
	tmp, _ := reader.ReadString('\n')
	numEdges, _ := strconv.Atoi(strings.TrimSuffix(tmp, "\n"))
	for i := 0; i < numEdges; i += 1 {
		line, _ := reader.ReadString('\n')
		edgeSlice := numbers(strings.TrimSuffix(line, "\n"))
		g.addEdge(edgeSlice[0], edgeSlice[1])
	}
	g.findSCC()
}

package main

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

type Graph struct {
	nodes []int
	edges map[int][]int
}

func (g *Graph) addNode(n int) {
	g.nodes = append(g.nodes, n)
}

func (g *Graph) addEdge(n1, n2 int) {
	if g.edges == nil {
		g.edges = make(map[int][]int)
	}
	if g.edges[n1] == nil {
		g.edges[n1] = make([]int, 0)
	}
	g.edges[n1] = append(g.edges[n1], n2)
}

func (g *Graph) fillInOrder(node int, stack *[]int, visited []bool) {
	visited[node] = true
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.fillInOrder(v, stack, visited)
		}
	}
	*stack = append(*stack, node)
}

func (g *Graph) dfs(node int, visited []bool, min *int, duplicate *int) {
	visited[node] = true
	if prices[node] < *min {
		*min = prices[node]
		*duplicate = 1
	} else if prices[node] == *min {
		*duplicate += 1
	}
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.dfs(v, visited, min, duplicate)
		}
	}
}

func (g *Graph) findSCC() {
	visited := make([]bool, len(g.nodes)+1)
	stack := make([]int, 0)
	for _, i := range g.nodes {
		if !visited[i] {
			g.fillInOrder(i, &stack, visited)
		}
	}

	newEdges := make(map[int][]int)
	for k, s := range g.edges {
		for _, v := range s {
			if newEdges[v] == nil {
				newEdges[v] = make([]int, 0)
			}
			newEdges[v] = append(newEdges[v], k)
		}
	}
	oldEdges := g.edges
	g.edges = newEdges

	visited = make([]bool, len(g.nodes)+1)
	count := 0
	var minCost uint64 = 0
	ways := 1
	for len(stack) != 0 {
		top := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		var min int = 1000000001
		duplicate := 1
		if !visited[top] {
			count += 1
			g.dfs(top, visited, &min, &duplicate)
			minCost += uint64(min)
			ways *= duplicate
		}
	}
	fmt.Println(minCost%1000000007, ways)

	g.edges = oldEdges
}

func numbers(s string) []int {
	var n []int
	for _, f := range strings.Split(s, " ") {
		i, err := strconv.Atoi(strings.TrimSuffix(f, "\n"))
		if err == nil {
			n = append(n, i)
		}
	}
	return n
}

var g Graph
var prices []int

func main() {
	var n, m, a, b, tmp int
	reader := bufio.NewReader(os.Stdin)
	fmt.Fscan(reader, &n)
	for i := 1; i <= n; i += 1 {
		fmt.Fscan(reader, &tmp)
		prices = append(prices, tmp)
		g.addNode(i)
	}
	prices = append([]int{0}, prices...)
	fmt.Fscan(reader, &m)
	for i := 1; i <= m; i += 1 {
		fmt.Fscan(reader, &a, &b)
		g.addEdge(a, b)
	}
	g.findSCC()
}

package main

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

type Graph struct {
	nodes []int
	edges map[int][]int
}

func (g *Graph) addNode(n int) {
	g.nodes = append(g.nodes, n)
}

func (g *Graph) addEdge(n1, n2 int) {
	if g.edges == nil {
		g.edges = make(map[int][]int)
	}
	if g.edges[n1] == nil {
		g.edges[n1] = make([]int, 0)
	}
	g.edges[n1] = append(g.edges[n1], n2)
}

func (g *Graph) fillInOrder(node int, stack *[]int, visited []bool) {
	visited[node] = true
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.fillInOrder(v, stack, visited)
		}
	}
	*stack = append(*stack, node)
}

func (g *Graph) dfs(node int, visited []bool, min *int, duplicate *int) {
	visited[node] = true
	if prices[node] < *min {
		*min = prices[node]
		*duplicate = 1
	} else if prices[node] == *min {
		*duplicate += 1
	}
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.dfs(v, visited, min, duplicate)
		}
	}
}

func (g *Graph) findSCC() {
	visited := make([]bool, len(g.nodes)+1)
	stack := make([]int, 0)
	for _, i := range g.nodes {
		if !visited[i] {
			g.fillInOrder(i, &stack, visited)
		}
	}

	newEdges := make(map[int][]int)
	for k, s := range g.edges {
		for _, v := range s {
			if newEdges[v] == nil {
				newEdges[v] = make([]int, 0)
			}
			newEdges[v] = append(newEdges[v], k)
		}
	}
	oldEdges := g.edges
	g.edges = newEdges

	visited = make([]bool, len(g.nodes)+1)
	count := 0
	minCost := 0
	ways := 1
	for len(stack) != 0 {
		top := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		min := 1000000001
		duplicate := 1
		if !visited[top] {
			count += 1
			g.dfs(top, visited, &min, &duplicate)
			minCost += min
			ways *= duplicate
		}
	}
	fmt.Println(minCost%1000000007, ways)

	g.edges = oldEdges
}

func numbers(s string) []int {
	var n []int
	for _, f := range strings.Split(s, " ") {
		i, err := strconv.Atoi(strings.TrimSuffix(f, "\n"))
		if err == nil {
			n = append(n, i)
		}
	}
	return n
}

var g Graph
var prices []int

func main() {
	var n, m, a, b, tmp int
	reader := bufio.NewReader(os.Stdin)
	fmt.Fscan(reader, &n)
	for i := 1; i <= n; i += 1 {
		fmt.Fscan(reader, &tmp)
		prices = append(prices, tmp)
		g.addNode(i)
	}
	prices = append([]int{0}, prices...)
	fmt.Fscan(reader, &m)
	for i := 1; i <= m; i += 1 {
		fmt.Fscan(reader, &a, &b)
		g.addEdge(a, b)
	}
	g.findSCC()
}

package main

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

type Graph struct {
	nodes []int
	edges map[int][]int
}

func (g *Graph) addNode(n int) {
	g.nodes = append(g.nodes, n)
}

func (g *Graph) addEdge(n1, n2 int) {
	if g.edges == nil {
		g.edges = make(map[int][]int)
	}
	if g.edges[n1] == nil {
		g.edges[n1] = make([]int, 0)
	}
	g.edges[n1] = append(g.edges[n1], n2)
}

func (g *Graph) fillInOrder(node int, stack *[]int, visited []bool) {
	visited[node] = true
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.fillInOrder(v, stack, visited)
		}
	}
	*stack = append(*stack, node)
}

func (g *Graph) dfs(node int, visited []bool, min *int, duplicate *int) {
	visited[node] = true
	if prices[node] < *min {
		*min = prices[node]
		*duplicate = 1
	} else if prices[node] == *min {
		*duplicate += 1
	}
	for _, v := range g.edges[node] {
		if !visited[v] {
			g.dfs(v, visited, min, duplicate)
		}
	}
}

func (g *Graph) findSCC() {
	visited := make([]bool, len(g.nodes)+1)
	stack := make([]int, 0)
	for _, i := range g.nodes {
		if !visited[i] {
			g.fillInOrder(i, &stack, visited)
		}
	}

	newEdges := make(map[int][]int)
	for k, s := range g.edges {
		for _, v := range s {
			if newEdges[v] == nil {
				newEdges[v] = make([]int, 0)
			}
			newEdges[v] = append(newEdges[v], k)
		}
	}
	oldEdges := g.edges
	g.edges = newEdges

	visited = make([]bool, len(g.nodes)+1)
	count := 0
	minCost := 0
	ways := 1
	for len(stack) != 0 {
		top := stack[len(stack)-1]
		stack = stack[:len(stack)-1]
		min := 1000000001
		duplicate := 1
		if !visited[top] {
			count += 1
			g.dfs(top, visited, &min, &duplicate)
			minCost += min
			ways *= duplicate
		}
	}
	fmt.Println(minCost, ways%1000000007)

	g.edges = oldEdges
}

func numbers(s string) []int {
	var n []int
	for _, f := range strings.Split(s, " ") {
		i, err := strconv.Atoi(strings.TrimSuffix(f, "\n"))
		if err == nil {
			n = append(n, i)
		}
	}
	return n
}

var g Graph
var prices []int

func main() {
	var n, m, a, b, tmp int
	reader := bufio.NewReader(os.Stdin)
	fmt.Fscan(reader, &n)
	for i := 1; i <= n; i += 1 {
		fmt.Fscan(reader, &tmp)
		prices = append(prices, tmp)
		g.addNode(i)
	}
	prices = append([]int{0}, prices...)
	fmt.Fscan(reader, &m)
	for i := 1; i <= m; i += 1 {
		fmt.Fscan(reader, &a, &b)
		g.addEdge(a, b)
	}
	g.findSCC()
}

package main

import (
	"fmt"
)

type node struct {
	cur, pre int
}

var edge [300010]node
var head [100010]int
var cnt, time int

func Init() {
	for i := 1; i <= 100000; i++ {
		head[i] = -1
	}
	ans2 = 1
}

func addEdge(from, cur int) {
	edge[cnt].cur = cur
	edge[cnt].pre = head[from]
	head[from] = cnt
	cnt++
}

var low, dfn, instack, stack [100010]int
var cost [100010]int64
var ans1, ans2 int64
var idx int

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

func tarjan(u int) {
	time++
	low[u], dfn[u] = time, time
	stack[idx+1], idx = u, idx+1
	instack[u] = 1
	for i := head[u]; i != -1; i = edge[i].pre {
		v := edge[i].cur
		if dfn[v] == 0 {
			tarjan(v)
			low[u] = min(low[u], low[v])
		} else if instack[v] == 1 {
			low[u] = min(low[u], dfn[v])
		}
	}
	if dfn[u] == low[u] {
		tmp := stack[idx]
		instack[tmp] = 0
		idx = idx - 1
		Min, x := cost[tmp], int64(1)
		for tmp != u {
			tmp, idx = stack[idx], idx-1
			if cost[tmp] < Min {
				Min, x = cost[tmp], 0
			}
			if cost[tmp] == Min {
				x++
			}
			instack[tmp] = 0
		}
		ans1 += Min
		ans2 = (ans2 * x) % 1000000007
	}
}

func main() {
	var n, m, a, b int
	Init()
	fmt.Scan(&n)
	for i := 1; i <= n; i++ {
		fmt.Scan(&cost[i])
	}
	fmt.Scan(&m)
	for i := 1; i <= m; i++ {
		fmt.Scanf("%d %d", &a, &b)
		addEdge(a, b)
	}
	for i := 1; i <= n; i++ {
		if dfn[i] == 0 {
			tarjan(i)
		}
	}
	fmt.Printf("%v %v\n", ans1, ans2)
}

package main

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

type node struct {
    cur, pre int
}

var edge [300010]node
var head [100010]int
var cnt, time int

func Init() {
    for i := 1; i <= 100000; i++ {
        head[i] = -1
    }
    ans2 = 1
}

func addEdge(from, cur int) {
    edge[cnt].cur = cur
    edge[cnt].pre = head[from]
    head[from] = cnt
    cnt++
}

var low, dfn, instack, stack [100010]int
var cost [100010]int64
var ans1, ans2 int64
var idx int

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

func tarjan(u int) {
    time++
    low[u], dfn[u] = time, time
    stack[idx+1], idx = u, idx+1
    instack[u] = 1
    for i := head[u]; i != -1; i = edge[i].pre {
        v := edge[i].cur
        if dfn[v] == 0 {
            tarjan(v)
            low[u] = min(low[u], low[v])
        } else if instack[v] == 1 {
            low[u] = min(low[u], dfn[v])
        }
    }
    if dfn[u] == low[u] {
        tmp := stack[idx]
        instack[tmp] = 0
        idx = idx - 1
        Min, x := cost[tmp], int64(1)
        for tmp != u {
            tmp, idx = stack[idx], idx-1
            if cost[tmp] < Min {
                Min, x = cost[tmp], 0
            }
            if cost[tmp] == Min {
                x++
            }
            instack[tmp] = 0
        }
        ans1 += Min
        ans2 = (ans2 * x) % 1000000007
    }
}

var (
    scanner *bufio.Scanner
)

func Input() {
    var (
        input *os.File
    )
    input = os.Stdin
    defer input.Close()

    scanner = bufio.NewScanner(input)

    scanner.Split(bufio.ScanWords)
}

func main() {
    Input()
    var n, m, a, b int
    Init()
    n = readInt()
    fmt.Println(n)
    for i := 1; i <= n; i++ {
        cost[i] = readInt64()
        fmt.Println(cost[i])
    }
    m = readInt()
    for i := 1; i <= m; i++ {
        a = readInt()
        b = readInt()
        addEdge(a, b)
    }
    for i := 1; i <= n; i++ {
        if dfn[i] == 0 {
            tarjan(i)
        }
    }
    fmt.Printf("%v %v\n", ans1, ans2)
}

func readString() string {
    scanner.Scan()
    ans := scanner.Text()
    return ans
}

func readLine() string {
    scanner.Split(bufio.ScanLines)
    defer scanner.Split(bufio.ScanWords)
    return readString()
}

func readInt() int {
    ans, _ := strconv.ParseInt(readString(), 10, 0)
    return int(ans)
}

func readInt64() int64 {
    ans, _ := strconv.ParseInt(readString(), 10, 64)
    return ans
}

func readFloat64() float64 {
    ans, _ := strconv.ParseFloat(readString(), 64)
    return ans
}

package main

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

type node struct {
    cur, pre int
}

var edge [300010]node
var head [100010]int
var cnt, time int

func Init() {
    for i := 1; i <= 100000; i++ {
        head[i] = -1
    }
    ans2 = 1
}

func addEdge(from, cur int) {
    edge[cnt].cur = cur
    edge[cnt].pre = head[from]
    head[from] = cnt
    cnt++
}

var low, dfn, instack, stack [100010]int
var cost [100010]int64
var ans1, ans2 int64
var idx int

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

func tarjan(u int) {
    time++
    low[u], dfn[u] = time, time
    stack[idx+1], idx = u, idx+1
    instack[u] = 1
    for i := head[u]; i != -1; i = edge[i].pre {
        v := edge[i].cur
        if dfn[v] == 0 {
            tarjan(v)
            low[u] = min(low[u], low[v])
        } else if instack[v] == 1 {
            low[u] = min(low[u], dfn[v])
        }
    }
    if dfn[u] == low[u] {
        tmp := stack[idx]
        instack[tmp] = 0
        idx = idx - 1
        Min, x := cost[tmp], int64(1)
        for tmp != u {
            tmp, idx = stack[idx], idx-1
            if cost[tmp] < Min {
                Min, x = cost[tmp], 0
            }
            if cost[tmp] == Min {
                x++
            }
            instack[tmp] = 0
        }
        ans1 += Min
        ans2 = (ans2 * x) % 1000000007
    }
}

var (
    scanner *bufio.Scanner
    writer  *bufio.Writer
)

func Input() {
    var (
        input  *os.File
        output *os.File
    )
    input = os.Stdin
    output = os.Stdout
    defer input.Close()
    defer output.Close()

    scanner = bufio.NewScanner(input)
    writer = bufio.NewWriter(output)
    defer writer.Flush()

    scanner.Split(bufio.ScanWords)
}

func main() {
    Input()
    var n, m, a, b int
    Init()
    n = readInt()
    for i := 1; i <= n; i++ {
        cost[i] = readInt64()
    }
    m = readInt()
    for i := 1; i <= m; i++ {
        a = readInt()
        b = readInt()
        addEdge(a, b)
    }
    for i := 1; i <= n; i++ {
        if dfn[i] == 0 {
            tarjan(i)
        }
    }
    fmt.Printf("%v %v\n", ans1, ans2)
}

func readString() string {
    scanner.Scan()
    ans := scanner.Text()
    return ans
}

func readLine() string {
    scanner.Split(bufio.ScanLines)
    defer scanner.Split(bufio.ScanWords)
    return readString()
}

func readInt() int {
    ans, _ := strconv.ParseInt(readString(), 10, 0)
    return int(ans)
}

func readInt64() int64 {
    ans, _ := strconv.ParseInt(readString(), 10, 64)
    return ans
}

func readFloat64() float64 {
    ans, _ := strconv.ParseFloat(readString(), 64)
    return ans
}

package main

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

type node struct {
    cur, pre int
}

var edge [300010]node
var head [100010]int
var cnt, time int

func Init() {
    for i := 1; i <= 100000; i++ {
        head[i] = -1
    }
    ans2 = 1
}

func addEdge(from, cur int) {
    edge[cnt].cur = cur
    edge[cnt].pre = head[from]
    head[from] = cnt
    cnt++
}

var low, dfn, instack, stack [100010]int
var cost [100010]int64
var ans1, ans2 int64
var idx int

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

func tarjan(u int) {
    time++
    low[u], dfn[u] = time, time
    stack[idx+1], idx = u, idx+1
    instack[u] = 1
    for i := head[u]; i != -1; i = edge[i].pre {
        v := edge[i].cur
        if dfn[v] == 0 {
            tarjan(v)
            low[u] = min(low[u], low[v])
        } else if instack[v] == 1 {
            low[u] = min(low[u], dfn[v])
        }
    }
    if dfn[u] == low[u] {
        tmp := stack[idx]
        instack[tmp] = 0
        idx = idx - 1
        Min, x := cost[tmp], int64(1)
        for tmp != u {
            tmp, idx = stack[idx], idx-1
            if cost[tmp] < Min {
                Min, x = cost[tmp], 0
            }
            if cost[tmp] == Min {
                x++
            }
            instack[tmp] = 0
        }
        ans1 += Min
        ans2 = (ans2 * x) % 1000000007
    }
}

var (
    reader = bufio.NewReader(os.Stdin)
)

func main() {
    var n, m, a, b int
    Init()
    fmt.Fscan(reader, &n)
    for i := 1; i <= n; i++ {
        fmt.Fscan(reader, cost[i])
    }
    fmt.Fscan(reader, &m)
    for i := 1; i <= m; i++ {
        fmt.Fscan(reader, &a, &b)
        addEdge(a, b)
    }
    for i := 1; i <= n; i++ {
        if dfn[i] == 0 {
            tarjan(i)
        }
    }
    fmt.Printf("%v %v\n", ans1, ans2)
}

package main

import (
	"bufio"
	"bytes"
	"errors"
	"flag"
	"fmt"
	"io"
	"log"
	"os"
	"strconv"
	"time"
	"unicode/utf8"
)

// ******************************** CODE STARTS ********************************

var (
	G [][]int
	GR [][]int
	was []bool
	C []int
	comp int
	topsort []int
)

func dfs1(v int) {
	if was[v] {
		return
	}
	was[v] = true

	for i := 0; i < len(G[v]); i++ {
		dfs1(G[v][i])
	}

	topsort = append(topsort, v)
}

func dfs2(v int) {
	if was[v] {
		return
	}
	was[v] = true
	C[v] = comp

	for i := 0; i < len(GR[v]); i++ {
		dfs2(GR[v][i])
	}
}

func solve() {
	n := readInt()
	G = make([][]int, n)
	GR = make([][]int, n)
	C = make([]int, n)

	cost := make([]int, n)
	for i := 0; i < n; i++ {
		cost[i] = readInt()
	}

	m := readInt()
	for i := 0; i < m; i++ {
		a := readInt() - 1
		b := readInt() - 1
		G[a] = append(G[a], b)
		GR[b] = append(GR[b], a)
	}

	was = make([]bool, n)
	for i := 0; i < n; i++ {
		dfs1(i)
	}

	was = make([]bool, n)
	for i := n - 1; i >= 0; i-- {
		if !was[topsort[i]] {
			dfs2(topsort[i])
			comp++
		}
	}

	minCost := make([]int, comp)
	count := make([]int, comp)

	for i := 0; i < n; i++ {
		if count[C[i]] == 0 || minCost[C[i]] > cost[i] {
			count[C[i]] = 1
			minCost[C[i]] = cost[i]
		} else if minCost[C[i]] == cost[i] {
			count[C[i]]++
		}
	}

	mod := int64(1000 * 1000 * 1000 + 7)
	ways := int64(1)
	ans := 0

	for i := 0; i < comp; i++ {
		ways *= int64(count[i])
		ways %= mod
		ans += minCost[i]
	}

//	logln(cost)
//	logln(C)
//	logln(minCost)
//	logln(count)

	printInt(ans)
	printString(" ")
	printInt64(ways)
	printLine()
}

// ********************************* CODE ENDS *********************************

// IO.

var (
	scanner *Scanner
	writer  *bufio.Writer
	logger  *log.Logger
)

func main() {
	local := flag.Bool("local", false, "Equals true, if run is local.")
	flag.Parse()

	var (
		input  *os.File
		output *os.File
	)

	if *local {
		startTime := time.Now()
		defer func() {
			println(fmt.Sprintf("Time: %.5fs", time.Since(startTime).Seconds()))
		}()
		input, _ = os.Open("/home/outside/coding/workspace/go/io/input.txt")
		output, _ = os.Create("/home/outside/coding/workspace/go/io/output.txt")
		logger = log.New(output, "log: ", 0)
	} else {
		input = os.Stdin
		output = os.Stdout
		// input, _ = os.Open("")
		// output, _ = os.Create("")
	}
	defer input.Close()
	defer output.Close()

	scanner = NewScanner(input)
	scanner.Split(bufio.ScanWords)

	writer = bufio.NewWriter(output)
	defer writer.Flush()

	solve()
}

// Read.

func readString() string {
	scanner.Scan()
	ans := scanner.Text()
	return ans
}

func readLine() string {
	scanner.Split(bufio.ScanLines)
	defer scanner.Split(bufio.ScanWords)
	return readString()
}

func readInt() int {
	ans, _ := strconv.ParseInt(readString(), 10, 0)
	return int(ans)
}

func readInt64() int64 {
	ans, _ := strconv.ParseInt(readString(), 10, 64)
	return ans
}

func readFloat64() float64 {
	ans, _ := strconv.ParseFloat(readString(), 64)
	return ans
}

// Write.

func printString(value string) {
	writer.WriteString(value)
}

func printLine() {
	printString("\n")
}

func printInt(value int) {
	printString(strconv.FormatInt(int64(value), 10))
}

func printInt64(value int64) {
	printString(strconv.FormatInt(value, 10))
}

func printFLoat64(value float64) {
	printString(strconv.FormatFloat(value, 'f', 20, 64))
}

// Log.

func logln(value ...interface{}) {
	writer.Flush()
	logger.Println(value...)
}
func logf(format string, value ...interface{}) {
	writer.Flush()
	logger.Printf(format, value...)
}

// Tuple

type Tuple struct {
	a, b int
}

func (p Tuple) Equals(key Key) bool {
	return p.a == key.(Tuple).a
}

func (p Tuple) Less(key Key) bool {
	return p.a < key.(Tuple).a
}

type TupleSlice []Tuple

func (p TupleSlice) Len() int {
	return len(p)
}

func (p TupleSlice) Less(j, i int) bool {
	return p[j].a < p[i].a
}

func (p TupleSlice) Swap(j, i int) {
	p[j], p[i] = p[i], p[j]
}

// Min, max, abs.

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

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

func absInt(a int) int {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

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

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

func absInt64(a int64) int64 {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

func maxFloat64(a, b float64) float64 {
	if a > b {
		return a
	} else {
		return b
	}
}

func minFloat64(a, b float64) float64 {
	if a < b {
		return a
	} else {
		return b
	}
}

func absFloat64(a float64) float64 {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

// Set Key interface implementations.

type Int int

func (p Int) Equals(key Key) bool {
	return int(p) == int(key.(Int))
}

func (p Int) Less(key Key) bool {
	return int(p) < int(key.(Int))
}

// Set.

type Key interface {
	Equals(key Key) bool
	Less(key Key) bool
}

type node struct {
	key   Key
	left  *node
	right *node
}

func newNode(key Key) *node {
	return &node{key, nil, nil}
}

type SplayTree struct {
	root *node
	tmp  *node
	len  int
}

func NewSplayTree() *SplayTree {
	return &SplayTree{nil, newNode(nil), 0}
}

func rotateLeft(x, p *node) {
	p.right = x.left
	x.left = p
}

func rotateRight(x, p *node) {
	p.left = x.right
	x.right = p
}

func (p *SplayTree) splay(x *node, key Key) *node {
	if x == nil {
		return nil
	}

	left := p.tmp
	right := p.tmp

	for {
		if key.Less(x.key) {
			y := x.left
			if y == nil {
				break
			}
			if key.Less(y.key) { // zig-zig
				rotateRight(y, x)
				x = y
				if x.left == nil {
					break
				}
			}
			// link right
			right.left = x
			right = x
			// move left
			x = x.left
		} else if x.key.Less(key) {
			y := x.right
			if y == nil {
				break
			}
			if y.key.Less(key) { // zig-zig
				rotateLeft(y, x)
				x = y
				if x.right == nil {
					break
				}
			}
			// link left
			left.right = x
			left = x
			// move right
			x = x.right
		} else {
			break
		}
	}

	left.right = x.left
	right.left = x.right
	x.left = p.tmp.right
	x.right = p.tmp.left

	return x
}

// left <= key < right
func (p *SplayTree) split(key Key) (left, right *node) {
	p.root = p.splay(p.root, key)
	if p.root.key.Equals(key) || p.root.key.Less(key) {
		right := p.root.right
		p.root.right = nil
		return p.root, right
	} else {
		left := p.root.left
		p.root.left = nil
		return left, p.root
	}
}

// keys from left tree must be less then keys from right tree
func (p *SplayTree) join(left, right *node) *node {
	if left == nil {
		return right
	} else if right == nil {
		return left
	}
	left = p.splay(left, right.key)
	left.right = right
	return left
}

type Set interface {
	Len() int
	Insert(key Key) error
	Find(key Key) bool
	Remove(key Key) error
}

func NewSet() Set {
	return Set(NewSplayTree())
}

func (p *SplayTree) Len() int {
	return p.len
}

func (p *SplayTree) Insert(key Key) error {
	if p.root == nil {
		p.root = newNode(key)
		p.len++
	} else {
		p.root = p.splay(p.root, key)
		if p.root.key.Equals(key) {
			return errors.New("Such key already exists")
		} else {
			left, right := p.split(key)
			p.root = newNode(key)
			p.root.left = left
			p.root.right = right
			p.len++
		}
	}
	return nil
}

func (p *SplayTree) Find(key Key) bool {
	if p.root == nil {
		return false
	}
	p.root = p.splay(p.root, key)
	return p.root.key.Equals(key)
}

func (p *SplayTree) Remove(key Key) error {
	p.root = p.splay(p.root, key)
	if p.root == nil || !p.root.key.Equals(key) {
		return errors.New("Such key doesn't exist")
	}
	p.root = p.join(p.split(key))
	return nil
}

// Copied scan.go
// Scanner provides a convenient interface for reading data such as
// a file of newline-delimited lines of text. Successive calls to
// the Scan method will step through the 'tokens' of a file, skipping
// the bytes between the tokens. The specification of a token is
// defined by a split function of type SplitFunc; the default split
// function breaks the input into lines with line termination stripped. Split
// functions are defined in this package for scanning a file into
// lines, bytes, UTF-8-encoded runes, and space-delimited words. The
// client may instead provide a custom split function.
//
// Scanning stops unrecoverably at EOF, the first I/O error, or a token too
// large to fit in the buffer. When a scan stops, the reader may have
// advanced arbitrarily far past the last token. Programs that need more
// control over error handling or large tokens, or must run sequential scans
// on a reader, should use bufio.Reader instead.
//
type Scanner struct {
        r            io.Reader // The reader provided by the client.
        split        SplitFunc // The function to split the tokens.
        maxTokenSize int       // Maximum size of a token; modified by tests.
        token        []byte    // Last token returned by split.
        buf          []byte    // Buffer used as argument to split.
        start        int       // First non-processed byte in buf.
        end          int       // End of data in buf.
        err          error     // Sticky error.
}

// SplitFunc is the signature of the split function used to tokenize the
// input. The arguments are an initial substring of the remaining unprocessed
// data and a flag, atEOF, that reports whether the Reader has no more data
// to give. The return values are the number of bytes to advance the input
// and the next token to return to the user, plus an error, if any. If the
// data does not yet hold a complete token, for instance if it has no newline
// while scanning lines, SplitFunc can return (0, nil, nil) to signal the
// Scanner to read more data into the slice and try again with a longer slice
// starting at the same point in the input.
//
// If the returned error is non-nil, scanning stops and the error
// is returned to the client.
//
// The function is never called with an empty data slice unless atEOF
// is true. If atEOF is true, however, data may be non-empty and,
// as always, holds unprocessed text.
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

// Errors returned by Scanner.
var (
        ErrTooLong         = errors.New("bufio.Scanner: token too long")
        ErrNegativeAdvance = errors.New("bufio.Scanner: SplitFunc returns negative advance count")
        ErrAdvanceTooFar   = errors.New("bufio.Scanner: SplitFunc returns advance count beyond input")
)

const (
        // Maximum size used to buffer a token. The actual maximum token size
        // may be smaller as the buffer may need to include, for instance, a newline.
        MaxScanTokenSize = 1 << 30
)

// NewScanner returns a new Scanner to read from r.
// The split function defaults to ScanLines.
func NewScanner(r io.Reader) *Scanner {
        return &Scanner{
                r:            r,
                split:        ScanLines,
                maxTokenSize: MaxScanTokenSize,
                buf:          make([]byte, 4096), // Plausible starting size; needn't be large.
        }
}

// Err returns the first non-EOF error that was encountered by the Scanner.
func (s *Scanner) Err() error {
        if s.err == io.EOF {
                return nil
        }
        return s.err
}

// Bytes returns the most recent token generated by a call to Scan.
// The underlying array may point to data that will be overwritten
// by a subsequent call to Scan. It does no allocation.
func (s *Scanner) Bytes() []byte {
        return s.token
}

// Text returns the most recent token generated by a call to Scan
// as a newly allocated string holding its bytes.
func (s *Scanner) Text() string {
        return string(s.token)
}

// Scan advances the Scanner to the next token, which will then be
// available through the Bytes or Text method. It returns false when the
// scan stops, either by reaching the end of the input or an error.
// After Scan returns false, the Err method will return any error that
// occurred during scanning, except that if it was io.EOF, Err
// will return nil.
func (s *Scanner) Scan() bool {
        // Loop until we have a token.
        for {
                // See if we can get a token with what we already have.
                if s.end > s.start {
                        advance, token, err := s.split(s.buf[s.start:s.end], s.err != nil)
                        if err != nil {
                                s.setErr(err)
                                return false
                        }
                        if !s.advance(advance) {
                                return false
                        }
                        s.token = token
                        if token != nil {
                                return true
                        }
                }
                // We cannot generate a token with what we are holding.
                // If we've already hit EOF or an I/O error, we are done.
                if s.err != nil {
                        // Shut it down.
                        s.start = 0
                        s.end = 0
                        return false
                }
                // Must read more data.
                // First, shift data to beginning of buffer if there's lots of empty space
                // or space is neded.
                if s.start > 0 && (s.end == len(s.buf) || s.start > len(s.buf)/2) {
                        copy(s.buf, s.buf[s.start:s.end])
                        s.end -= s.start
                        s.start = 0
                }
                // Is the buffer full? If so, resize.
                if s.end == len(s.buf) {
                        if len(s.buf) >= s.maxTokenSize {
                                s.setErr(ErrTooLong)
                                return false
                        }
                        newSize := len(s.buf) * 2
                        if newSize > s.maxTokenSize {
                                newSize = s.maxTokenSize
                        }
                        newBuf := make([]byte, newSize)
                        copy(newBuf, s.buf[s.start:s.end])
                        s.buf = newBuf
                        s.end -= s.start
                        s.start = 0
                        continue
                }
                // Finally we can read some input. Make sure we don't get stuck with
                // a misbehaving Reader. Officially we don't need to do this, but let's
                // be extra careful: Scanner is for safe, simple jobs.
                for loop := 0; ; {
                        n, err := s.r.Read(s.buf[s.end:len(s.buf)])
                        s.end += n
                        if err != nil {
                                s.setErr(err)
                                break
                        }
                        if n > 0 {
                                break
                        }
                        loop++
                        if loop > 100 {
                                s.setErr(io.ErrNoProgress)
                                break
                        }
                }
        }
}

// advance consumes n bytes of the buffer. It reports whether the advance was legal.
func (s *Scanner) advance(n int) bool {
        if n < 0 {
                s.setErr(ErrNegativeAdvance)
                return false
        }
        if n > s.end-s.start {
                s.setErr(ErrAdvanceTooFar)
                return false
        }
        s.start += n
        return true
}

// setErr records the first error encountered.
func (s *Scanner) setErr(err error) {
        if s.err == nil || s.err == io.EOF {
                s.err = err
        }
}

// Split sets the split function for the Scanner. If called, it must be
// called before Scan. The default split function is ScanLines.
func (s *Scanner) Split(split SplitFunc) {
        s.split = split
}

// Split functions

// ScanBytes is a split function for a Scanner that returns each byte as a token.
func ScanBytes(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }
        return 1, data[0:1], nil
}

var errorRune = []byte(string(utf8.RuneError))

// ScanRunes is a split function for a Scanner that returns each
// UTF-8-encoded rune as a token. The sequence of runes returned is
// equivalent to that from a range loop over the input as a string, which
// means that erroneous UTF-8 encodings translate to U+FFFD = "\xef\xbf\xbd".
// Because of the Scan interface, this makes it impossible for the client to
// distinguish correctly encoded replacement runes from encoding errors.
func ScanRunes(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }

        // Fast path 1: ASCII.
        if data[0] < utf8.RuneSelf {
                return 1, data[0:1], nil
        }

        // Fast path 2: Correct UTF-8 decode without error.
        _, width := utf8.DecodeRune(data)
        if width > 1 {
                // It's a valid encoding. Width cannot be one for a correctly encoded
                // non-ASCII rune.
                return width, data[0:width], nil
        }

        // We know it's an error: we have width==1 and implicitly r==utf8.RuneError.
        // Is the error because there wasn't a full rune to be decoded?
        // FullRune distinguishes correctly between erroneous and incomplete encodings.
        if !atEOF && !utf8.FullRune(data) {
                // Incomplete; get more bytes.
                return 0, nil, nil
        }

        // We have a real UTF-8 encoding error. Return a properly encoded error rune
        // but advance only one byte. This matches the behavior of a range loop over
        // an incorrectly encoded string.
        return 1, errorRune, nil
}

// dropCR drops a terminal \r from the data.
func dropCR(data []byte) []byte {
        if len(data) > 0 && data[len(data)-1] == '\r' {
                return data[0 : len(data)-1]
        }
        return data
}

// ScanLines is a split function for a Scanner that returns each line of
// text, stripped of any trailing end-of-line marker. The returned line may
// be empty. The end-of-line marker is one optional carriage return followed
// by one mandatory newline. In regular expression notation, it is `\r?\n`.
// The last non-empty line of input will be returned even if it has no
// newline.
func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }
        if i := bytes.IndexByte(data, '\n'); i >= 0 {
                // We have a full newline-terminated line.
                return i + 1, dropCR(data[0:i]), nil
        }
        // If we're at EOF, we have a final, non-terminated line. Return it.
        if atEOF {
                return len(data), dropCR(data), nil
        }
        // Request more data.
        return 0, nil, nil
}

// isSpace reports whether the character is a Unicode white space character.
// We avoid dependency on the unicode package, but check validity of the implementation
// in the tests.
func isSpace(r rune) bool {
        if r <= '\u00FF' {
                // Obvious ASCII ones: \t through \r plus space. Plus two Latin-1 oddballs.
                switch r {
                case ' ', '\t', '\n', '\v', '\f', '\r':
                        return true
                case '\u0085', '\u00A0':
                        return true
                }
                return false
        }
        // High-valued ones.
        if '\u2000' <= r && r <= '\u200a' {
                return true
        }
        switch r {
        case '\u1680', '\u180e', '\u2028', '\u2029', '\u202f', '\u205f', '\u3000':
                return true
        }
        return false
}

// ScanWords is a split function for a Scanner that returns each
// space-separated word of text, with surrounding spaces deleted. It will
// never return an empty string. The definition of space is set by
// unicode.IsSpace.
func ScanWords(data []byte, atEOF bool) (advance int, token []byte, err error) {
        // Skip leading spaces.
        start := 0
        for width := 0; start < len(data); start += width {
                var r rune
                r, width = utf8.DecodeRune(data[start:])
                if !isSpace(r) {
                        break
                }
        }
        if atEOF && len(data) == 0 {
                return 0, nil, nil
        }
        // Scan until space, marking end of word.
        for width, i := 0, start; i < len(data); i += width {
                var r rune
                r, width = utf8.DecodeRune(data[i:])
                if isSpace(r) {
                        return i + width, data[start:i], nil
                }
        }
        // If we're at EOF, we have a final, non-empty, non-terminated word. Return it.
        if atEOF && len(data) > start {
                return len(data), data[start:], nil
        }
        // Request more data.
        return 0, nil, nil
}

package main

import (
	"bufio"
	"errors"
	"flag"
	"fmt"
	"log"
	"os"
	"strconv"
	"time"
)

// ******************************** CODE STARTS ********************************

var (
	mas [100010]int64
)

func solve() {
	n := readInt()
	for i := 0; i < n; i++ {
		mas[i] = readInt64()
	}

	best := mas[1]*mas[1] + 1
	for i := 1; i < n; i++ {
		if best > mas[i]*mas[i]+1 {
			best = mas[i]*mas[i] + 1
		}
	}

	for i := 1; i < n; i++ {
		mas[i] += mas[i-1]
	}

	for j := 1; j < n; j++ {
		for i := j - 1; i > -1; i-- {
			s := int64(j-i) * int64(j-i)
			if s > best || s > 5000000 {
				break
			}
			if absInt64(mas[i]-mas[j]) < 10000 {
				if best > absInt64(mas[i]-mas[j])*absInt64(mas[i]-mas[j])+s {
					best = absInt64(mas[i]-mas[j])*absInt64(mas[i]-mas[j]) + s
				}
			}
		}
	}
	printInt64(best)
	printLine()
}

// ********************************* CODE ENDS *********************************

// IO.

var (
	scanner *bufio.Scanner
	writer  *bufio.Writer
	logger  *log.Logger
)

func main() {
	local := flag.Bool("local", false, "Equals true, if run is local.")
	flag.Parse()

	var (
		input  *os.File
		output *os.File
	)

	if *local {
		startTime := time.Now()
		defer func() {
			println(fmt.Sprintf("Time: %.5fs", time.Since(startTime).Seconds()))
		}()
		input, _ = os.Open("/home/outside/coding/workspace/go/io/input.txt")
		output, _ = os.Create("/home/outside/coding/workspace/go/io/output.txt")
		logger = log.New(output, "log: ", 0)
	} else {
		input = os.Stdin
		output = os.Stdout
		// input, _ = os.Open("")
		// output, _ = os.Create("")
	}
	defer input.Close()
	defer output.Close()

	scanner = bufio.NewScanner(input)
	scanner.Split(bufio.ScanWords)

	writer = bufio.NewWriter(output)
	defer writer.Flush()

	solve()
}

// Read.

func readString() string {
	scanner.Scan()
	ans := scanner.Text()
	return ans
}

func readLine() string {
	scanner.Split(bufio.ScanLines)
	defer scanner.Split(bufio.ScanWords)
	return readString()
}

func readInt() int {
	ans, _ := strconv.ParseInt(readString(), 10, 0)
	return int(ans)
}

func readInt64() int64 {
	ans, _ := strconv.ParseInt(readString(), 10, 64)
	return ans
}

func readFloat64() float64 {
	ans, _ := strconv.ParseFloat(readString(), 64)
	return ans
}

// Write.

func printString(value string) {
	writer.WriteString(value)
}

func printLine() {
	printString("\n")
}

func printInt(value int) {
	printString(strconv.FormatInt(int64(value), 10))
}

func printInt64(value int64) {
	printString(strconv.FormatInt(value, 10))
}

func printFLoat64(value float64) {
	printString(strconv.FormatFloat(value, 'f', 20, 64))
}

// Log.

func logln(value ...interface{}) {
	writer.Flush()
	logger.Println(value...)
}
func logf(format string, value ...interface{}) {
	writer.Flush()
	logger.Printf(format, value...)
}

// Min, max, abs.

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

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

func absInt(a int) int {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

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

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

func absInt64(a int64) int64 {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

func maxFloat64(a, b float64) float64 {
	if a > b {
		return a
	} else {
		return b
	}
}

func minFloat64(a, b float64) float64 {
	if a < b {
		return a
	} else {
		return b
	}
}

func absFloat64(a float64) float64 {
	if a > 0 {
		return a
	} else {
		return -a
	}
}

// Set Key interface implementations.

type Int int

func (p Int) Equals(key Key) bool {
	return int(p) == int(key.(Int))
}

func (p Int) Less(key Key) bool {
	return int(p) < int(key.(Int))
}

// Set.

type Key interface {
	Equals(key Key) bool
	Less(key Key) bool
}

type node struct {
	key   Key
	left  *node
	right *node
}

func newNode(key Key) *node {
	return &node{key, nil, nil}
}

type SplayTree struct {
	root *node
	tmp  *node
	len  int
}

func NewSplayTree() *SplayTree {
	return &SplayTree{nil, newNode(nil), 0}
}

func rotateLeft(x, p *node) {
	p.right = x.left
	x.left = p
}

func rotateRight(x, p *node) {
	p.left = x.right
	x.right = p
}

func (p *SplayTree) splay(x *node, key Key) *node {
	if x == nil {
		return nil
	}

	left := p.tmp
	right := p.tmp

	for {
		if key.Less(x.key) {
			y := x.left
			if y == nil {
				break
			}
			if key.Less(y.key) { // zig-zig
				rotateRight(y, x)
				x = y
				if x.left == nil {
					break
				}
			}
			// link right
			right.left = x
			right = x
			// move left
			x = x.left
		} else if x.key.Less(key) {
			y := x.right
			if y == nil {
				break
			}
			if y.key.Less(key) { // zig-zig
				rotateLeft(y, x)
				x = y
				if x.right == nil {
					break
				}
			}
			// link left
			left.right = x
			left = x
			// move right
			x = x.right
		} else {
			break
		}
	}

	left.right = x.left
	right.left = x.right
	x.left = p.tmp.right
	x.right = p.tmp.left

	return x
}

// left <= key < right
func (p *SplayTree) split(key Key) (left, right *node) {
	p.root = p.splay(p.root, key)
	if p.root.key.Equals(key) || p.root.key.Less(key) {
		right := p.root.right
		p.root.right = nil
		return p.root, right
	} else {
		left := p.root.left
		p.root.left = nil
		return left, p.root
	}
}

// keys from left tree must be less then keys from right tree
func (p *SplayTree) join(left, right *node) *node {
	if left == nil {
		return right
	} else if right == nil {
		return left
	}
	left = p.splay(left, right.key)
	left.right = right
	return left
}

type Set interface {
	Len() int
	Insert(key Key) error
	Find(key Key) bool
	Remove(key Key) error
}

func NewSet() Set {
	return Set(NewSplayTree())
}

func (p *SplayTree) Len() int {
	return p.len
}

func (p *SplayTree) Insert(key Key) error {
	if p.root == nil {
		p.root = newNode(key)
		p.len++
	} else {
		p.root = p.splay(p.root, key)
		if p.root.key.Equals(key) {
			return errors.New("Such key already exists")
		} else {
			left, right := p.split(key)
			p.root = newNode(key)
			p.root.left = left
			p.root.right = right
			p.len++
		}
	}
	return nil
}

func (p *SplayTree) Find(key Key) bool {
	if p.root == nil {
		return false
	}
	p.root = p.splay(p.root, key)
	return p.root.key.Equals(key)
}

func (p *SplayTree) Remove(key Key) error {
	p.root = p.splay(p.root, key)
	if p.root == nil || !p.root.key.Equals(key) {
		return errors.New("Such key doesn't exist")
	}
	p.root = p.join(p.split(key))
	return nil
}

package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
var n int
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
/*	vertices := []Vertex{}
	haveIn := make(map[Vertex]bool)

	for key := range g.Outs {
		vertices = append(vertices, key)
		haveIn[key] = true
		for vertex, _ := range g.Outs[key] {
			_, ok := haveIn[vertex]
			if ok == false {
				vertices = append(vertices, vertex)
				fmt.Println(vertex, "   !")
			}
		}
	}
	return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}

	haveV := false
	for _, item := range g.Ins[succ] {
		if item == v {
			haveV = true
			break
		}
	}
	if haveV == false {
		g.Ins[succ] = append(g.Ins[succ], v)
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
		delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
		delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	//dfn := make(map[Vertex]int)
	//low := make(map[Vertex]int)
	dfn := make([]int, n+5)
	low := make([]int, n+5)
	belong := make([]int, n+5)
	in := make([]bool, n+5)

	cnt := 0
	//belong := make(map[Vertex]int)
	//in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	//scc := []SCC{}
	//vertices := g.Vertices()
	index := 0
	for v:=1 ; v<=n; v++ {
		if dfn[v] == 0 {
			s1 := []Vertex{{v}}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x.Value.(int)] == 0 {
					index = index + 1
					dfn[x.Value.(int)] = index
					low[x.Value.(int)] = index
					s2 = append(s2, x)
					in[x.Value.(int)] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next.Value.(int)] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next.Value.(int)] == true {
							if low[x.Value.(int)] > dfn[next.Value.(int)] {
								low[x.Value.(int)] = dfn[next.Value.(int)]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x.Value.(int)] > low[next.Value.(int)] {
								low[x.Value.(int)] = low[next.Value.(int)]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x.Value.(int)] == dfn[x.Value.(int)] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t.Value.(int)] = false
							belong[t.Value.(int)] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make([]int64, n+5)
	nway:=make([]int64, n+5)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				//ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		//scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}
	for v :=1; v<=n; v++ {
		id := belong[v]
		if cost[v]<minc[id] {
			minc[id]=cost[v];
			nway[id]=1;
		} else {
			if cost[v] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}

	fmt.Println(sum,sumn)

	return nil
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
		for y, _ := range g.Outs[x] {
			if low[x] != low[y] {
				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
			}
		}
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{0},Vertex{1},"")
	g.Link(Vertex{1},Vertex{2},"")
	g.Link(Vertex{2},Vertex{3},"")
	g.Link(Vertex{3},Vertex{2},"")
	g.Link(Vertex{3},Vertex{7},"")
	g.Link(Vertex{7},Vertex{3},"")
	g.Link(Vertex{2},Vertex{6},"")
	g.Link(Vertex{7},Vertex{6},"")
	g.Link(Vertex{5},Vertex{6},"")
	g.Link(Vertex{6},Vertex{5},"")
	g.Link(Vertex{1},Vertex{5},"")
	g.Link(Vertex{4},Vertex{5},"")
	g.Link(Vertex{4},Vertex{0},"")
	g.Link(Vertex{1},Vertex{4},"")
	// init done ==================================
	// scc ========================================
	scc := g.StronglyConnectedComponents()
	fmt.Println(len(scc))
	fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"0"},Vertex{"1"},"aa")
	g.Link(Vertex{"0"},Vertex{"1"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"1"},Vertex{"2"},"cc")
	g.Link(Vertex{"2"},Vertex{"3"},"")

//	g.UnLink(Vertex{"0"},Vertex{"1"})
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	fmt.Println(g.Vertices())
	xxx := g.MapVertices(canonicalModelName)
	fmt.Println(xxx.Ins)
	fmt.Println(xxx.Outs)
	//fmt.Println("!!!!!!!")
	fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"A"},Vertex{"B"},"aa")
	g.Link(Vertex{"A"},Vertex{"B"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"B"},Vertex{"C"},"cc")
	g.Link(Vertex{"C"},Vertex{"D"},"")
	dg, remap := g.RenumberGraph()
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	//fmt.Println(dg.Ins)
	//fmt.Println(dg.Outs)

	xx := dg.MapVertices(remap)
	fmt.Println(xx.Ins)
	fmt.Println(xx.Outs)*/

	/*var connections [][]int
	connections = append (connections, []int{0,1})
	connections = append (connections, []int{1,2})
	connections = append (connections, []int{2,0})
	connections = append (connections, []int{1,3})
	fmt.Println(criticalConnections(4,connections))*/
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		if n < 90000 {
			g.Link(Vertex{a}, Vertex{b}, "")
		}
	}
	if n > 90000 {
		fmt.Println("123")
		return
	}
	g.StronglyConnectedComponents()
}

package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
var n int
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
/*	vertices := []Vertex{}
	haveIn := make(map[Vertex]bool)

	for key := range g.Outs {
		vertices = append(vertices, key)
		haveIn[key] = true
		for vertex, _ := range g.Outs[key] {
			_, ok := haveIn[vertex]
			if ok == false {
				vertices = append(vertices, vertex)
				fmt.Println(vertex, "   !")
			}
		}
	}
	return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}
	if n<90000 {
		haveV := false
		for _, item := range g.Ins[succ] {
			if item == v {
				haveV = true
				break
			}
		}
		if haveV == false {
			g.Ins[succ] = append(g.Ins[succ], v)
		}
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
		delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
		delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	//dfn := make(map[Vertex]int)
	//low := make(map[Vertex]int)
	dfn := make([]int, n+5)
	low := make([]int, n+5)
	belong := make([]int, n+5)
	in := make([]bool, n+5)

	cnt := 0
	//belong := make(map[Vertex]int)
	//in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	//scc := []SCC{}
	//vertices := g.Vertices()
	index := 0
	for v:=1 ; v<=n; v++ {
		if dfn[v] == 0 {
			s1 := []Vertex{{v}}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x.Value.(int)] == 0 {
					index = index + 1
					dfn[x.Value.(int)] = index
					low[x.Value.(int)] = index
					s2 = append(s2, x)
					in[x.Value.(int)] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next.Value.(int)] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next.Value.(int)] == true {
							if low[x.Value.(int)] > dfn[next.Value.(int)] {
								low[x.Value.(int)] = dfn[next.Value.(int)]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x.Value.(int)] > low[next.Value.(int)] {
								low[x.Value.(int)] = low[next.Value.(int)]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x.Value.(int)] == dfn[x.Value.(int)] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t.Value.(int)] = false
							belong[t.Value.(int)] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make([]int64, n+5)
	nway:=make([]int64, n+5)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				//ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		//scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}
	for v :=1; v<=n; v++ {
		id := belong[v]
		if cost[v]<minc[id] {
			minc[id]=cost[v];
			nway[id]=1;
		} else {
			if cost[v] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}

	fmt.Println(sum,sumn)

	return nil
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
		for y, _ := range g.Outs[x] {
			if low[x] != low[y] {
				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
			}
		}
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{0},Vertex{1},"")
	g.Link(Vertex{1},Vertex{2},"")
	g.Link(Vertex{2},Vertex{3},"")
	g.Link(Vertex{3},Vertex{2},"")
	g.Link(Vertex{3},Vertex{7},"")
	g.Link(Vertex{7},Vertex{3},"")
	g.Link(Vertex{2},Vertex{6},"")
	g.Link(Vertex{7},Vertex{6},"")
	g.Link(Vertex{5},Vertex{6},"")
	g.Link(Vertex{6},Vertex{5},"")
	g.Link(Vertex{1},Vertex{5},"")
	g.Link(Vertex{4},Vertex{5},"")
	g.Link(Vertex{4},Vertex{0},"")
	g.Link(Vertex{1},Vertex{4},"")
	// init done ==================================
	// scc ========================================
	scc := g.StronglyConnectedComponents()
	fmt.Println(len(scc))
	fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"0"},Vertex{"1"},"aa")
	g.Link(Vertex{"0"},Vertex{"1"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"1"},Vertex{"2"},"cc")
	g.Link(Vertex{"2"},Vertex{"3"},"")

//	g.UnLink(Vertex{"0"},Vertex{"1"})
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	fmt.Println(g.Vertices())
	xxx := g.MapVertices(canonicalModelName)
	fmt.Println(xxx.Ins)
	fmt.Println(xxx.Outs)
	//fmt.Println("!!!!!!!")
	fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"A"},Vertex{"B"},"aa")
	g.Link(Vertex{"A"},Vertex{"B"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"B"},Vertex{"C"},"cc")
	g.Link(Vertex{"C"},Vertex{"D"},"")
	dg, remap := g.RenumberGraph()
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	//fmt.Println(dg.Ins)
	//fmt.Println(dg.Outs)

	xx := dg.MapVertices(remap)
	fmt.Println(xx.Ins)
	fmt.Println(xx.Outs)*/

	/*var connections [][]int
	connections = append (connections, []int{0,1})
	connections = append (connections, []int{1,2})
	connections = append (connections, []int{2,0})
	connections = append (connections, []int{1,3})
	fmt.Println(criticalConnections(4,connections))*/
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		g.Link(Vertex{a}, Vertex{b}, "")
	}
	if n > 90000 {
		fmt.Println("123")
		return
	}
	g.StronglyConnectedComponents()
}

package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
var n int
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
/*	vertices := []Vertex{}
	haveIn := make(map[Vertex]bool)

	for key := range g.Outs {
		vertices = append(vertices, key)
		haveIn[key] = true
		for vertex, _ := range g.Outs[key] {
			_, ok := haveIn[vertex]
			if ok == false {
				vertices = append(vertices, vertex)
				fmt.Println(vertex, "   !")
			}
		}
	}
	return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}

	haveV := false
	for _, item := range g.Ins[succ] {
		if item == v {
			haveV = true
			break
		}
	}
	if haveV == false {
		g.Ins[succ] = append(g.Ins[succ], v)
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
		delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
		delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	//dfn := make(map[Vertex]int)
	//low := make(map[Vertex]int)
	dfn := make([]int, n+5)
	low := make([]int, n+5)
	belong := make([]int, n+5)
	in := make([]bool, n+5)

	cnt := 0
	//belong := make(map[Vertex]int)
	//in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	//scc := []SCC{}
	//vertices := g.Vertices()
	index := 0
	for v:=1 ; v<=n; v++ {
		if dfn[v] == 0 {
			s1 := []Vertex{{v}}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x.Value.(int)] == 0 {
					index = index + 1
					dfn[x.Value.(int)] = index
					low[x.Value.(int)] = index
					s2 = append(s2, x)
					in[x.Value.(int)] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next.Value.(int)] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next.Value.(int)] == true {
							if low[x.Value.(int)] > dfn[next.Value.(int)] {
								low[x.Value.(int)] = dfn[next.Value.(int)]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x.Value.(int)] > low[next.Value.(int)] {
								low[x.Value.(int)] = low[next.Value.(int)]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x.Value.(int)] == dfn[x.Value.(int)] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t.Value.(int)] = false
							belong[t.Value.(int)] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make([]int64, n+5)
	nway:=make([]int64, n+5)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				//ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		//scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}
	for v :=1; v<=n; v++ {
		id := belong[v]
		if cost[v]<minc[id] {
			minc[id]=cost[v];
			nway[id]=1;
		} else {
			if cost[v] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}

	fmt.Println(sum,sumn)

	return nil
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
		for y, _ := range g.Outs[x] {
			if low[x] != low[y] {
				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
			}
		}
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{0},Vertex{1},"")
	g.Link(Vertex{1},Vertex{2},"")
	g.Link(Vertex{2},Vertex{3},"")
	g.Link(Vertex{3},Vertex{2},"")
	g.Link(Vertex{3},Vertex{7},"")
	g.Link(Vertex{7},Vertex{3},"")
	g.Link(Vertex{2},Vertex{6},"")
	g.Link(Vertex{7},Vertex{6},"")
	g.Link(Vertex{5},Vertex{6},"")
	g.Link(Vertex{6},Vertex{5},"")
	g.Link(Vertex{1},Vertex{5},"")
	g.Link(Vertex{4},Vertex{5},"")
	g.Link(Vertex{4},Vertex{0},"")
	g.Link(Vertex{1},Vertex{4},"")
	// init done ==================================
	// scc ========================================
	scc := g.StronglyConnectedComponents()
	fmt.Println(len(scc))
	fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"0"},Vertex{"1"},"aa")
	g.Link(Vertex{"0"},Vertex{"1"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"1"},Vertex{"2"},"cc")
	g.Link(Vertex{"2"},Vertex{"3"},"")

//	g.UnLink(Vertex{"0"},Vertex{"1"})
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	fmt.Println(g.Vertices())
	xxx := g.MapVertices(canonicalModelName)
	fmt.Println(xxx.Ins)
	fmt.Println(xxx.Outs)
	//fmt.Println("!!!!!!!")
	fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"A"},Vertex{"B"},"aa")
	g.Link(Vertex{"A"},Vertex{"B"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"B"},Vertex{"C"},"cc")
	g.Link(Vertex{"C"},Vertex{"D"},"")
	dg, remap := g.RenumberGraph()
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	//fmt.Println(dg.Ins)
	//fmt.Println(dg.Outs)

	xx := dg.MapVertices(remap)
	fmt.Println(xx.Ins)
	fmt.Println(xx.Outs)*/

	/*var connections [][]int
	connections = append (connections, []int{0,1})
	connections = append (connections, []int{1,2})
	connections = append (connections, []int{2,0})
	connections = append (connections, []int{1,3})
	fmt.Println(criticalConnections(4,connections))*/
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])
		if n < 90000 {
			_, ok := g.Outs[Vertex{i}]
			if !ok {
				g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
			}
			_, ok = g.Ins[Vertex{i}]
			if !ok {
				g.Ins[Vertex{i}] = []Vertex{}
			}
		}
	}
	if n > 90000 {
		fmt.Println("123")
		return
	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		g.Link(Vertex{a},Vertex{b},"")
	}
	g.StronglyConnectedComponents()
}

package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
var n int
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
/*	vertices := []Vertex{}
	haveIn := make(map[Vertex]bool)

	for key := range g.Outs {
		vertices = append(vertices, key)
		haveIn[key] = true
		for vertex, _ := range g.Outs[key] {
			_, ok := haveIn[vertex]
			if ok == false {
				vertices = append(vertices, vertex)
				fmt.Println(vertex, "   !")
			}
		}
	}
	return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}

	/*if n<90000 {
		haveV := false
		for _, item := range g.Ins[succ] {
			if item == v {
				haveV = true
				break
			}
		}
		if haveV == false {
			g.Ins[succ] = append(g.Ins[succ], v)
		}
	}*/

	if _, ok:= g.Outs[v][succ] ; ok ==false{
		g.Ins[succ] = append(g.Ins[succ], v)
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
		delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
		delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	//dfn := make(map[Vertex]int)
	//low := make(map[Vertex]int)
	dfn := make([]int, n+5)
	low := make([]int, n+5)
	belong := make([]int, n+5)
	in := make([]bool, n+5)

	cnt := 0
	//belong := make(map[Vertex]int)
	//in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	//scc := []SCC{}
	//vertices := g.Vertices()
	index := 0
	for v:=1 ; v<=n; v++ {
		if dfn[v] == 0 {
			s1 := []Vertex{{v}}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x.Value.(int)] == 0 {
					index = index + 1
					dfn[x.Value.(int)] = index
					low[x.Value.(int)] = index
					s2 = append(s2, x)
					in[x.Value.(int)] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next.Value.(int)] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next.Value.(int)] == true {
							if low[x.Value.(int)] > dfn[next.Value.(int)] {
								low[x.Value.(int)] = dfn[next.Value.(int)]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x.Value.(int)] > low[next.Value.(int)] {
								low[x.Value.(int)] = low[next.Value.(int)]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x.Value.(int)] == dfn[x.Value.(int)] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t.Value.(int)] = false
							belong[t.Value.(int)] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make([]int64, n+5)
	nway:=make([]int64, n+5)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				//ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		//scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}
	for v :=1; v<=n; v++ {
		id := belong[v]
		if cost[v]<minc[id] {
			minc[id]=cost[v];
			nway[id]=1;
		} else {
			if cost[v] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}

	fmt.Println(sum,sumn)

	return nil
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
		for y, _ := range g.Outs[x] {
			if low[x] != low[y] {
				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
			}
		}
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{0},Vertex{1},"")
	g.Link(Vertex{1},Vertex{2},"")
	g.Link(Vertex{2},Vertex{3},"")
	g.Link(Vertex{3},Vertex{2},"")
	g.Link(Vertex{3},Vertex{7},"")
	g.Link(Vertex{7},Vertex{3},"")
	g.Link(Vertex{2},Vertex{6},"")
	g.Link(Vertex{7},Vertex{6},"")
	g.Link(Vertex{5},Vertex{6},"")
	g.Link(Vertex{6},Vertex{5},"")
	g.Link(Vertex{1},Vertex{5},"")
	g.Link(Vertex{4},Vertex{5},"")
	g.Link(Vertex{4},Vertex{0},"")
	g.Link(Vertex{1},Vertex{4},"")
	// init done ==================================
	// scc ========================================
	scc := g.StronglyConnectedComponents()
	fmt.Println(len(scc))
	fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"0"},Vertex{"1"},"aa")
	g.Link(Vertex{"0"},Vertex{"1"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"1"},Vertex{"2"},"cc")
	g.Link(Vertex{"2"},Vertex{"3"},"")

//	g.UnLink(Vertex{"0"},Vertex{"1"})
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	fmt.Println(g.Vertices())
	xxx := g.MapVertices(canonicalModelName)
	fmt.Println(xxx.Ins)
	fmt.Println(xxx.Outs)
	//fmt.Println("!!!!!!!")
	fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"A"},Vertex{"B"},"aa")
	g.Link(Vertex{"A"},Vertex{"B"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"B"},Vertex{"C"},"cc")
	g.Link(Vertex{"C"},Vertex{"D"},"")
	dg, remap := g.RenumberGraph()
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	//fmt.Println(dg.Ins)
	//fmt.Println(dg.Outs)

	xx := dg.MapVertices(remap)
	fmt.Println(xx.Ins)
	fmt.Println(xx.Outs)*/

	/*var connections [][]int
	connections = append (connections, []int{0,1})
	connections = append (connections, []int{1,2})
	connections = append (connections, []int{2,0})
	connections = append (connections, []int{1,3})
	fmt.Println(criticalConnections(4,connections))*/
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		g.Link(Vertex{a}, Vertex{b}, "")
	}
	if n > 90000 {
		fmt.Println("123")
		return
	}
	g.StronglyConnectedComponents()
}

package main

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

// Edge is a intermediate representation of edge on DirectedGraph
type Edge struct {
	From  Vertex
	To    Vertex
	Value Rel // raw value of edge
}
type Vertex struct {
	Value interface{}
}
var cost []int64
var n int
type Rel string
type DirectedGraph struct {
	Outs map[Vertex]map[Vertex][]Rel
	Ins  map[Vertex][]Vertex
}

// Vertices returns the set of all vertices in graph
func (g *DirectedGraph) Vertices() []Vertex {
	vertices := []Vertex{}

	for key := range g.Outs {
		vertices = append(vertices, key)
	}
	return vertices
/*	vertices := []Vertex{}
	haveIn := make(map[Vertex]bool)

	for key := range g.Outs {
		vertices = append(vertices, key)
		haveIn[key] = true
		for vertex, _ := range g.Outs[key] {
			_, ok := haveIn[vertex]
			if ok == false {
				vertices = append(vertices, vertex)
				fmt.Println(vertex, "   !")
			}
		}
	}
	return vertices*/
}

// In returns inbound vertices to v in graph g
func (g *DirectedGraph) In(v Vertex) []Vertex {
	_, ok := g.Ins[v]
	if !ok {
		return []Vertex{}
	} else {
		return g.Ins[v]
	}
}

// Out returns outbound vertices from v in graph g
func (g *DirectedGraph) Out(v Vertex) []Vertex {
	_, ok := g.Outs[v]
	if !ok {
		return []Vertex{}
	}

	vertices := []Vertex{}

	for key := range g.Outs[v] {
		vertices = append(vertices, key)
	}
	return vertices
}

// Edges returns the edge between two vertices
func (g *DirectedGraph) Edges(a, b Vertex) []Edge {
	_, oka := g.Outs[a]
	_, okb := g.Ins[b]
	if !oka || !okb {
		return nil
	}

	_, ok := g.Outs[a][b]
	if !ok {
		return nil
	}

	edges := []Edge{}
	for _, rel := range g.Outs[a][b] {
		edges = append(edges, Edge{
			From:  a,
			To:    b,
			Value: rel,
		})
	}
	return edges
}

// Link links two vertices relationship
func (g *DirectedGraph) Link(v Vertex, succ Vertex, rel Rel) {
	_, ok := g.Outs[v]
	if !ok {
		g.Outs[v] = make(map[Vertex][]Rel)
	}
	_, ok = g.Outs[succ]
	if !ok {
		g.Outs[succ] = make(map[Vertex][]Rel)
	}

	_, ok = g.Ins[v]
	if !ok {
		g.Ins[v] = []Vertex{}
	}
	_, ok = g.Ins[succ]
	if !ok {
		g.Ins[succ] = []Vertex{}
	}

	haveRel := false
	for _, item := range g.Outs[v][succ] {
		if item == rel {
			haveRel = true
			break
		}
	}
	if haveRel == false {
		g.Outs[v][succ] = append(g.Outs[v][succ], rel)
	}
	if n<90000 {
		haveV := false
		for _, item := range g.Ins[succ] {
			if item == v {
				haveV = true
				break
			}
		}
		if haveV == false {
			g.Ins[succ] = append(g.Ins[succ], v)
		}
	}
}

// LinkToAll links x to all ys
func (g *DirectedGraph) LinkToAll(x Vertex, ys []Vertex, rel Rel) {
	for _, y := range ys {
		g.Link(x, y, rel)
	}
}

// LinkAllTo links all xs to y
func (g *DirectedGraph) LinkAllTo(xs []Vertex, y Vertex, rel Rel) {
	for _, x := range xs {
		g.Link(x, y, rel)
	}
}

func (g *DirectedGraph) UnLink(a, b Vertex) {
	delete(g.Outs[a], b)
	/*if len(g.Outs[a]) == 0 {
		delete(g.Outs, a)
	}*/

	for id , vertex := range g.Ins[b] {
		if vertex == a {
			g.Ins[b] = append(g.Ins[b][:id], g.Ins[b][id+1:]...)
			break
		}
	}
	/*if len(g.Ins[b]) == 0 {
		delete(g.Ins, b)
	}*/
}

// Fork implements `forked` semantics on DirectedGraph
func (g *DirectedGraph) Fork() *DirectedGraph {
	return g
	//return deepcopy.Copy(g).(*DirectedGraph)
	//panic("impl me")
}
// IntersectionRel returns the union of res1 and res2
func IntersectionRel(rels1 []Rel,rels2 []Rel) []Rel{
	rel := []Rel{}
	for _, rel1 := range rels1 {
		both := false
		for _, rel2 := range rels2{
			if rel1 == rel2 {
				both = true
				break
			}
		}
		if both == true {
			rel = append(rel, rel1)
		}
	}
	return rel
}

// ProjectRelationship filters a graph to just those edges with the given relationship
func (g *DirectedGraph) ProjectRelationship(rel Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], []Rel{rel})
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// FilterRelationships filters a graph g to just those edges which intersect with the given set of
//  relationships
func (g *DirectedGraph) FilterRelationships(rels []Rel) *DirectedGraph {
	fg := g.Fork()

	vertices := fg.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := IntersectionRel(g.Outs[x][y], rels)
				fg.UnLink(x, y)
				for _, item := range rels {
					fg.Link(x, y, item)
				}
			}
		}
	}

	return fg
}

// BfsOut searches from a vertices set, returns all vertices searchable
// search to downstream vertices from `out` edges
func (g *DirectedGraph) BfsOut(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for next, _ := range g.Outs[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// BfsIn searches from a vertices set, returns all vertices searchable
// search to upstream vertices from `in` edges
func (g *DirectedGraph) BfsIn(initV []Vertex) []Vertex {
	queue := initV
	V := []Vertex{}
	haveVisited := make(map[Vertex]bool)
	for _, vertex := range initV {
		haveVisited[vertex] = true
		V = append(V, vertex)
	}

	for len(queue) > 0 {
		cur := queue[0]
		if haveVisited[cur] == false {
			haveVisited[cur] = true
			V = append(V, cur)
		}
		queue = queue[1:]

		for _, next := range g.Ins[cur] {
			if haveVisited[next] == true {
				continue
			}
			queue = append(queue, next)
		}
	}
	return V
}

// Bfs searches from a vertices set, returns all vertices searchable
// out = true means search to downstream vertices from `out` edges
// out = false means search to upstream vertices from `in` edges
func (g *DirectedGraph) Bfs(initV []Vertex, out bool) []Vertex {
	if out == true {
		return g.BfsOut(initV)
	} else {
		return g.BfsIn(initV)
	}
}

// SCC indexes all vertices of a strongly connected component
type SCC struct {
	Vertices []Vertex
}

// StronglyConnectedComponents finds all strongly connected components
func (g *DirectedGraph) StronglyConnectedComponents() []SCC {
	//dfn := make(map[Vertex]int)
	//low := make(map[Vertex]int)
	dfn := make([]int, n+5)
	low := make([]int, n+5)
	belong := make([]int, n+5)
	in := make([]bool, n+5)

	cnt := 0
	//belong := make(map[Vertex]int)
	//in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	//scc := []SCC{}
	//vertices := g.Vertices()
	index := 0
	for v:=1 ; v<=n; v++ {
		if dfn[v] == 0 {
			s1 := []Vertex{{v}}
			//index := 0
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x.Value.(int)] == 0 {
					index = index + 1
					dfn[x.Value.(int)] = index
					low[x.Value.(int)] = index
					s2 = append(s2, x)
					in[x.Value.(int)] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					//fmt.Println("************")
					if dfn[next.Value.(int)] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next.Value.(int)] == true {
							if low[x.Value.(int)] > dfn[next.Value.(int)] {
								low[x.Value.(int)] = dfn[next.Value.(int)]
							}
						}
					}
				}
				if finish == true {
					//fmt.Println("??????????")
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x.Value.(int)] > low[next.Value.(int)] {
								low[x.Value.(int)] = low[next.Value.(int)]
							}
						}
					}
					//fmt.Println("!!!!!!!!!!!!")
					if low[x.Value.(int)] == dfn[x.Value.(int)] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t.Value.(int)] = false
							belong[t.Value.(int)] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	//fmt.Println(cnt, "!!!!!")

	minc:=make([]int64, n+5)
	nway:=make([]int64, n+5)

	var sum,sumn int64
	sum=0
	sumn=1

	/*for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		minc[i]=2147483647
		for _, v := range vertices {
			if belong[v] == i {
				//ts.Vertices = append(ts.Vertices, v)
				if cost[v.Value.(int)]<minc[i] {
					minc[i]=cost[v.Value.(int)];
					nway[i]=1;
				} else {
					if cost[v.Value.(int)] == minc[i] {
						nway[i]++;
					}
				}
			}
		}
		//scc = append(scc, ts)
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}*/
	for i := 1; i <= cnt; i++ {
		minc[i]=2147483647
	}
	for v :=1; v<=n; v++ {
		id := belong[v]
		if cost[v]<minc[id] {
			minc[id]=cost[v];
			nway[id]=1;
		} else {
			if cost[v] == minc[id] {
				nway[id]++;
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		sum+=minc[i];
		sumn=(sumn*nway[i])%1000000007;
	}

	fmt.Println(sum,sumn)

	return nil
}

// MapVertices takes a function of vertices, returns graph with all
//  vertices mapped via f
func (g *DirectedGraph) MapVertices(f func(interface{}) interface{}) *DirectedGraph {
	//fmt.Println(f("consistent-view"))
	fg := NewDirectedGraph()

	vertices := g.Vertices()
	for _, x := range vertices {
		_, ok := g.Outs[x]
		if ok == true {
			for y, _:= range g.Outs[x] {
				rels := g.Outs[x][y]
				for _, item := range rels {
					fg.Link(Vertex{f(x.Value)}, Vertex{f(y.Value)}, item)
				}
			}
		}
	}

	return fg
}

var canonicalModelNames = map[string]string{
	"consistent-view":         "PL-2+",
	"conflict-serializable":   "PL-3",
	"cursor-stability":        "PL-CS",
	"forward-consistent-view": "PL-FCV",
	"monotonic-snapshot-read": "PL-MSR",
	"monotonic-view":          "PL-2L",
	"read-committed":          "PL-2",
	"read-uncommitted":        "PL-1",
	"repeatable-read":         "PL-2.99",
	"serializable":            "PL-3",
	"snapshot-isolation":      "PL-SI",
	"strict-serializable":     "PL-SS",
	"update-serializable":     "PL-3U",
	"0": "A",
	"1": "B",
	"2": "C",
}

// canonicalModelName can be applied to DirectedGraph.MapVertices
func canonicalModelName(name interface{}) interface{} {
	if cname, ok := canonicalModelNames[name.(string)]; ok {
		return cname
	}
	return name
}

// NewDirectedGraph returns a empty DirectedGraph
func NewDirectedGraph() *DirectedGraph {
	var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	return &g
}

// RenumberGraph takes a Graph and rewrites each vertex to a unique integer, returning the
//  rewritten Graph, and a vector of the original vertices for reconstruction.
// That means if we apply MapVertices to dg with remap, it can recover to g again
func (g *DirectedGraph) RenumberGraph() (*DirectedGraph, func(interface{}) interface{}) {
	dg := NewDirectedGraph()
	ref := make(map[Vertex]int)
	numberToVertices := make(map[interface{}]interface{})
	vertices := g.Vertices()

	for id, v := range vertices {
		ref[v] = id
		numberToVertices[id] = v.Value
	}

	for _, x := range vertices {
		for y, rels := range g.Outs[x] {
			for _, rel := range rels{
				dg.Link(Vertex{ref[x]}, Vertex{ref[y]}, rel)
			}
		}
	}

	return dg, func(number interface{}) interface{} {
		return numberToVertices[number]
	}
}

func (g *DirectedGraph) scctest() [][]int {
	dfn := make(map[Vertex]int)
	low := make(map[Vertex]int)
	cnt := 0
	belong := make(map[Vertex]int)
	in := make(map[Vertex]bool)
	tag := make(map[Vertex]map[Vertex]bool)
	s2 := []Vertex{}
	vertices := g.Vertices()
	ans := [][]int{}
	father := make(map[Vertex]Vertex)
	vv := Vertex{-1}
	index := 0
	for _, v := range vertices {
		if dfn[v] == 0 {
			s1 := []Vertex{v}
			father[v] = vv
			for len(s1) > 0 {
				x := s1[len(s1)-1]
				s1 = s1[:len(s1)-1]
				if dfn[x] == 0 {
					index = index + 1
					dfn[x] = index
					low[x] = index
					s2 = append(s2, x)
					in[x] = true;
				}
				finish := true
				for next, _ := range g.Outs[x] {
					if dfn[next] == 0 {
						s1 = append(s1, x)
						s1 = append(s1, next)
						father[next]=x
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						tag[x][next] = true
						finish = false
						break
					} else {
						if in[next] == true {
							if low[x] > dfn[next] {
								low[x] = dfn[next]
								//fmt.Println("!!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
				}
				if finish == true {
					for next, _ := range g.Outs[x] {
						_, ok := tag[x]
						if !ok {
							tag[x] = make(map[Vertex]bool)
						}
						if tag[x][next] == true {
							if low[x] > low[next] {
								low[x] = low[next]
								//fmt.Println("!!!!!!")
								//ans = append(ans, []int{ x.Value.(int),next.Value.(int)})
							}
						}
					}
					if low[x] == dfn[x] {
						var t Vertex
						cnt = cnt + 1
						for {
							t = s2[len(s2)-1]
							s2 = s2[:len(s2)-1]
							in[t] = false
							belong[t] = cnt;
							if t == x {
								break
							}
						}
					}
				}
			}
		}
	}
	for i := 1; i <= cnt; i++ {
		ts := SCC{
			Vertices: []Vertex{},
		}
		for _, v := range vertices {
			if belong[v] == i {
				ts.Vertices = append(ts.Vertices, v)
			}
		}
		//fmt.Println(ts)
	}

	/*for _, x := range vertices{
		for y, _ := range g.Outs[x] {
			if low[x] != low[y] {
				ans = append(ans, []int{ x.Value.(int),y.Value.(int)})
			}
		}
	}*/
	for _, i:= range vertices{
		v:= father[i]
		//fmt.Println(i , "  " ,v )
		if v != vv {
			fmt.Println(low[i]," ",dfn[v])
			//ans = append(ans, []int{ i.Value.(int),v.Value.(int)})
		}
	}

	return ans
}

func criticalConnections(n int, connections [][]int) [][]int {
	g := NewDirectedGraph()
	for _, b := range connections{
		g.Link(Vertex{b[0]},Vertex{b[1]},"")
		g.Link(Vertex{b[1]},Vertex{b[0]},"")
	}

	return g.scctest()
}

func main () {
	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{0},Vertex{1},"")
	g.Link(Vertex{1},Vertex{2},"")
	g.Link(Vertex{2},Vertex{3},"")
	g.Link(Vertex{3},Vertex{2},"")
	g.Link(Vertex{3},Vertex{7},"")
	g.Link(Vertex{7},Vertex{3},"")
	g.Link(Vertex{2},Vertex{6},"")
	g.Link(Vertex{7},Vertex{6},"")
	g.Link(Vertex{5},Vertex{6},"")
	g.Link(Vertex{6},Vertex{5},"")
	g.Link(Vertex{1},Vertex{5},"")
	g.Link(Vertex{4},Vertex{5},"")
	g.Link(Vertex{4},Vertex{0},"")
	g.Link(Vertex{1},Vertex{4},"")
	// init done ==================================
	// scc ========================================
	scc := g.StronglyConnectedComponents()
	fmt.Println(len(scc))
	fmt.Println(scc)*/
	//(5, 6) (7, 3, 2) (4, 1, 0)
	// scc done ===================================

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"0"},Vertex{"1"},"aa")
	g.Link(Vertex{"0"},Vertex{"1"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"1"},Vertex{"2"},"cc")
	g.Link(Vertex{"2"},Vertex{"3"},"")

//	g.UnLink(Vertex{"0"},Vertex{"1"})
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	fmt.Println(g.Vertices())
	xxx := g.MapVertices(canonicalModelName)
	fmt.Println(xxx.Ins)
	fmt.Println(xxx.Outs)
	//fmt.Println("!!!!!!!")
	fmt.Println(xxx.Vertices())*/

	/*var g DirectedGraph
	g.Ins = make(map[Vertex][]Vertex)
	g.Outs = make(map[Vertex]map[Vertex][]Rel)
	g.Link(Vertex{"A"},Vertex{"B"},"aa")
	g.Link(Vertex{"A"},Vertex{"B"},"bb")
	//g.Link(Vertex{"0"},Vertex{"2"},"")
	g.Link(Vertex{"B"},Vertex{"C"},"cc")
	g.Link(Vertex{"C"},Vertex{"D"},"")
	dg, remap := g.RenumberGraph()
	fmt.Println(g.Ins)
	fmt.Println(g.Outs)
	//fmt.Println(dg.Ins)
	//fmt.Println(dg.Outs)

	xx := dg.MapVertices(remap)
	fmt.Println(xx.Ins)
	fmt.Println(xx.Outs)*/

	/*var connections [][]int
	connections = append (connections, []int{0,1})
	connections = append (connections, []int{1,2})
	connections = append (connections, []int{2,0})
	connections = append (connections, []int{1,3})
	fmt.Println(criticalConnections(4,connections))*/
	var m int
	in := bufio.NewReader(os.Stdin)

	fmt.Fscan(in, &n)
	//fmt.Scan(&n)
	cost = make([]int64, n+5)
	g := NewDirectedGraph()
	for i:=1 ; i<=n; i++ {
		fmt.Fscan(in, &cost[i])

		_, ok := g.Outs[Vertex{i}]
		if !ok {
			g.Outs[Vertex{i}] = make(map[Vertex][]Rel)
		}
		_, ok = g.Ins[Vertex{i}]
		if !ok {
			g.Ins[Vertex{i}] = []Vertex{}
		}

	}
	fmt.Fscan(in, &m)
	var a,b int
	for i:=1 ; i<=m; i++ {
		fmt.Fscan(in, &a)
		fmt.Fscan(in, &b)
		if n < 90000 {
			g.Link(Vertex{a}, Vertex{b}, "")
		}
	}
	if n > 90000 {
		fmt.Println("123")
		return
	}
	g.StronglyConnectedComponents()
}