import java.io.OutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintWriter; import java.util.Arrays; import java.io.BufferedWriter; import java.util.InputMismatchException; import java.io.IOException; import java.util.ArrayList; import java.util.List; import java.util.stream.Stream; import java.io.Writer; import java.io.OutputStreamWriter; import java.io.InputStream; /** * Built using CHelper plug-in * Actual solution is at the top * * @author lewin */ public class random_heap_lewin { public static void main(String[] args) { InputStream inputStream = System.in; OutputStream outputStream = System.out; InputReader in = new InputReader(inputStream); OutputWriter out = new OutputWriter(outputStream); RandomHeap solver = new RandomHeap(); solver.solve(1, in, out); out.close(); } static class RandomHeap { int mod = 1000000007; int[] cap; int[] ss; int[] inv; List[] tree; int[] sz; int[][][] dp; public void solve(int testNumber, InputReader in, OutputWriter out) { int n = in.nextInt(); tree = LUtils.genArrayList(n); inv = new int[n + 1]; inv[1] = 1; for (int i = 2; i <= n; i++) inv[i] = (int) (1L * (mod - mod / i) * inv[mod % i] % mod); cap = new int[n + 1]; int rt = -1; for (int i = 0; i < n; i++) { cap[i] = in.nextInt(); int parent = in.nextInt() - 1; if (parent != -1) { tree[parent].add(i); } else { rt = i; } } ss = AUtils.unique(cap); sz = new int[n]; dfs0(rt); dp = new int[n][ss.length][]; out.printf("%d\n", AUtils.sum(dfs(rt, 1), mod)); } int dfs0(int node) { sz[node] = 1; for (int x : tree[node]) sz[node] += dfs0(x); return sz[node]; } int[] dfs(int node, int range) { if (range == ss.length) return new int[0]; if (dp[node][range] != null) return dp[node][range]; int[] ret = new int[sz[node] + 1]; ret[0] = AUtils.sum(dfs(node, range + 1), mod); int lo = ss[range - 1], hi = ss[range]; int cprob = (int) (Math.max(0, Math.min(cap[node], hi) - Math.max(0, lo)) * Utils.inv(cap[node], mod) % mod); if (cprob == 0) return dp[node][range] = ret; ret[1] = cprob; int sumsize = 1; for (int x : tree[node]) { int[] a = dfs(x, range); sumsize += sz[x]; for (int j = sumsize; j >= 1; j--) { ret[j] = (int) (1L * ret[j] * a[0] % mod); for (int take = 1; take <= sz[x] && take <= j - 1; take++) { ret[j] = (int) ((ret[j] + 1L * ret[j - take] * a[take]) % mod); } } } for (int i = 1; i <= sz[node]; i++) { ret[i] = (int) (1L * ret[i] * inv[i] % mod); } return dp[node][range] = ret; } } static class InputReader { private InputStream stream; private byte[] buf = new byte[1 << 16]; private int curChar; private int numChars; public InputReader(InputStream stream) { this.stream = stream; } public int read() { if (this.numChars == -1) { throw new InputMismatchException(); } else { if (this.curChar >= this.numChars) { this.curChar = 0; try { this.numChars = this.stream.read(this.buf); } catch (IOException var2) { throw new InputMismatchException(); } if (this.numChars <= 0) { return -1; } } return this.buf[this.curChar++]; } } public int nextInt() { int c; for (c = this.read(); isSpaceChar(c); c = this.read()) { ; } byte sgn = 1; if (c == 45) { sgn = -1; c = this.read(); } int res = 0; while (c >= 48 && c <= 57) { res *= 10; res += c - 48; c = this.read(); if (isSpaceChar(c)) { return res * sgn; } } throw new InputMismatchException(); } public static boolean isSpaceChar(int c) { return c == 32 || c == 10 || c == 13 || c == 9 || c == -1; } } static class AUtils { public static int sum(int[] arr, int mod) { int ans = 0; for (int a : arr) { ans += a; if (ans >= mod) ans -= mod; } return ans; } public static void sort(int[] arr) { shuffle(arr); Arrays.sort(arr); } public static void shuffle(int[] arr) { for (int i = 1; i < arr.length; i++) { int j = (int) (Math.random() * (i + 1)); if (i != j) { int t = arr[i]; arr[i] = arr[j]; arr[j] = t; } } } public static int[] unique(int[] a) { a = a.clone(); sort(a); int sz = 1; for (int i = 1; i < a.length; i++) { if (a[i] != a[sz - 1]) { a[sz++] = a[i]; } } return Arrays.copyOf(a, sz); } } static class LUtils { public static List[] genArrayList(int size) { return Stream.generate(ArrayList::new).limit(size).toArray(List[]::new); } } static class Utils { public static long inv(long N, long M) { long x = 0, lastx = 1, y = 1, lasty = 0, q, t, a = N, b = M; while (b != 0) { q = a / b; t = a % b; a = b; b = t; t = x; x = lastx - q * x; lastx = t; t = y; y = lasty - q * y; lasty = t; } return (lastx + M) % M; } } static class OutputWriter { private final PrintWriter writer; public OutputWriter(OutputStream outputStream) { writer = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream))); } public OutputWriter(Writer writer) { this.writer = new PrintWriter(writer); } public void printf(String format, Object... objects) { writer.printf(format, objects); } public void close() { writer.close(); } } }