Problem:
Score : 100 points

Problem Statement

There is a tree with N vertices, numbered 1, 2, \ldots, N.
For each i (1 \leq i \leq N - 1), the i-th edge connects Vertex x_i and y_i.

Taro has decided to paint each vertex in white or black.
Here, it is not allowed to paint two adjacent vertices both in black.

Find the number of ways in which the vertices can be painted, modulo 10^9 + 7.

Constraints

All values in input are integers.

1 \leq N \leq 10^5

1 \leq x_i, y_i \leq N

The given graph is a tree.

Input

Input is given from Standard Input in the following format:

N
x_1 y_1
x_2 y_2
:
x_{N - 1} y_{N - 1}

Output

Print the number of ways in which the vertices can be painted, modulo 10^9 + 7.

Sample Input 1

3
1 2
2 3

Sample Output 1

5

There are five ways to paint the vertices, as follows:

Sample Input 2

4
1 2
1 3
1 4

Sample Output 2

9

There are nine ways to paint the vertices, as follows:

Sample Input 3

1

Sample Output 3

2

Sample Input 4

10
8 5
10 8
6 5
1 5
4 8
2 10
3 6
9 2
1 7

Sample Output 4

157

Solution in C# (Mono 4.6.2.0) (judge verdict: Accepted)

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;

namespace AtCoder
{
	public class Program
	{
		static void Main()
		{
			var cin = new Scanner();
			int n = cin.Int();

			var tree = new Rerooting<Color>(
				n,
				(x, y) => {
					return new Color {
						Black = x.Black * y.Black + x.Black * y.Others + x.Others * y.Black,
						Others = x.Others * y.Others,
					};
				},
				x => {
					return new Color {
						Black = x.Others,
						Others = x.Black + x.Others,
					};
				},
				new Color { Others = 1, Black = 0 });

			for (int i = 0; i < n - 1; i++) {
				int x = cin.Int() - 1;
				int y = cin.Int() - 1;
				tree.AddEdge(x, y);
				tree.AddEdge(y, x);
			}

			var ret = tree.Build(0, true);
			ModInt ans = ret[0].Black + ret[0].Others;
			Console.WriteLine(ans.Value);
		}

		struct Color
		{	
			public ModInt Black { get; set; }
			public ModInt Others { get; set; }
		}
	}

	public class Rerooting<T>
	{
		private readonly int n_;
		private readonly Func<T, T, T> merge_;
		private readonly Func<T, T> calculate_;
		private readonly T unit_;
		private readonly List<int>[] to_;
		private readonly T[][] dp_;
		private readonly T[] result_;
		private int[] reverseIndexes_;

		public Rerooting(
			int n,
			Func<T, T, T> merge,
			Func<T, T> calculate,
			T unit)
		{
			n_ = n;
			merge_ = merge;
			calculate_ = calculate;
			unit_ = unit;

			to_ = new List<int>[n];
			dp_ = new T[n][];
			result_ = new T[n];
			for (int i = 0; i < n; i++) {
				to_[i] = new List<int>();
				result_[i] = unit_;
			}
		}

		public void AddEdge(int a, int b)
		{
			to_[a].Add(b);
		}

		public T[] Build(int root = 0, bool doseOnlyTreeDp = false)
		{
			DfsForTreeDP(root);
			if (doseOnlyTreeDp == false) {
				BfsForReroot(root);
			}

			return result_;
		}

		private void DfsForTreeDP(int v)
		{
			{
				var parents = new int[n_];
				var indexes = new int[n_];
				reverseIndexes_ = new int[n_];
				var visited = new bool[n_];
				var routeStack = new Stack<int>(n_);
				var tempStack = new Stack<int>(n_);
				routeStack.Push(v);
				tempStack.Push(v);
				visited[v] = true;
				parents[v] = -1;

				while (tempStack.Count > 0) {
					int current = tempStack.Pop();
					dp_[current] = new T[to_[current].Count];
					for (int i = 0; i < to_[current].Count; i++) {
						int next = to_[current][i];
						if (visited[next]) {
							reverseIndexes_[current] = i;
							continue;
						}

						visited[next] = true;
						parents[next] = current;
						indexes[next] = i;
						routeStack.Push(next);
						tempStack.Push(next);
					}
				}

				while (routeStack.Count > 0) {
					int target = routeStack.Pop();
					T accum = unit_;
					for (int i = 0; i < to_[target].Count; i++) {
						int child = to_[target][i];
						if (child == parents[target]) {
							continue;
						}

						accum = merge_(accum, dp_[target][i]);
					}

					result_[target] = calculate_(accum);
					if (parents[target] >= 0) {
						dp_[parents[target]][indexes[target]] = result_[target];
					}
				}
			}
		}

		private void BfsForReroot(int first)
		{
			int max = 0;
			for (int i = 0; i < n_; i++) {
				max = Math.Max(max, to_[i].Count);
			}

			var accumL = new T[max + 1];
			var accumR = new T[max + 1];

			var q = new Queue<BfsInfo>(n_);
			q.Enqueue(new BfsInfo(first, -1));
			while (q.Count > 0) {
				var current = q.Dequeue();
				int count = to_[current.V].Count;

				accumL[0] = unit_;
				for (int i = 0; i < count; i++) {
					accumL[i + 1] = merge_(accumL[i], dp_[current.V][i]);
				}

				accumR[count] = unit_;
				for (int i = count - 1; i >= 0; i--) {
					accumR[i] = merge_(accumR[i + 1], dp_[current.V][i]);
				}

				result_[current.V] = calculate_(accumL[count]);

				for (int i = 0; i < count; i++) {
					int next = to_[current.V][i];
					if (next == current.P) {
						continue;
					}

					T reverse = calculate_(merge_(accumL[i], accumR[i + 1]));
					dp_[next][reverseIndexes_[next]] = reverse;

					q.Enqueue(new BfsInfo(next, current.V));
				}
			}
		}

		private struct BfsInfo
		{
			public int V { get; set; }
			public int P { get; set; }

			public BfsInfo(int v, int p)
			{
				V = v;
				P = p;
			}
		}
	}

	public struct ModInt
	{
		public static long P { get; set; } = (long)1e9 + 7;

		public static ModInt Pow(ModInt value, long k)
		{
			return Pow(value.Value, k);
		}

		public static ModInt Pow(long value, long k)
		{
			long ret = 1;
			for (k %= P - 1; k > 0; k >>= 1, value = value * value % P) {
				if ((k & 1) == 1) {
					ret = ret * value % P;
				}
			}
			return new ModInt(ret);
		}

		public static ModInt Inverse(ModInt value)
		{
			return Pow(value, P - 2);
		}

		public long Value;

		public ModInt(long value)
		{
			value %= P;
			if (value < 0) {
				value += P;
			}

			Value = value;
		}

		public static ModInt operator +(ModInt lhs, ModInt rhs)
		{
			lhs.Value += rhs.Value;
			if (lhs.Value >= P) {
				lhs.Value -= P;
			}
			return lhs;
		}

		public static ModInt operator -(ModInt lhs, ModInt rhs)
		{
			lhs.Value -= rhs.Value;
			if (lhs.Value < 0) {
				lhs.Value += P;
			}

			return lhs;
		}

		public static ModInt operator *(ModInt lhs, ModInt rhs)
		{
			return new ModInt(lhs.Value * rhs.Value % P);
		}
		public static ModInt operator /(ModInt lhs, ModInt rhs)
		{
			long exp = P - 2;
			while (exp > 0) {
				if (exp % 2 > 0) {
					lhs *= rhs;
				}

				rhs *= rhs;
				exp /= 2;
			}

			return lhs;
		}

		public static implicit operator ModInt(long n)
		{
			n %= P;
			if (n < 0) {
				n += P;
			}

			return new ModInt(n);
		}

		public override string ToString()
		{
			return Value.ToString();
		}
	}

	public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
	{
		private readonly Func<TKey, TValue> initialzier_;
		public HashMap(Func<TKey, TValue> initialzier)
			: base()
		{
			initialzier_ = initialzier;
		}

		public HashMap(Func<TKey, TValue> initialzier, int capacity)
			: base(capacity)
		{
			initialzier_ = initialzier;
		}

		new public TValue this[TKey key]
		{
			get
			{
				if (ContainsKey(key) == false) {
					base[key] = initialzier_(key);
				}

				return base[key];
			}

			set { base[key] = value; }
		}
	}

	public static class Helper
	{
		public static void UpdateMin<T>(ref T target, T value) where T : IComparable<T>
			=> target = target.CompareTo(value) > 0 ? value : target;

		public static void UpdateMin<T>(ref T target, T value, Action<T> onUpdated) where T : IComparable<T>
		{
			if (target.CompareTo(value) > 0) {
				target = value;
				onUpdated(value);
			}
		}

		public static void UpdateMax<T>(ref T target, T value) where T : IComparable<T>
			=> target = target.CompareTo(value) < 0 ? value : target;
		public static void UpdateMax<T>(ref T target, T value, Action<T> onUpdated) where T : IComparable<T>
		{
			if (target.CompareTo(value) < 0) {
				target = value;
				onUpdated(value);
			}
		}

		public static T[] Array<T>(int n, Func<int, T> init)
			=> Enumerable.Range(0, n).Select(x => init(x)).ToArray();
		public static List<T> List<T>(int n, Func<int, T> init)
			=> Enumerable.Range(0, n).Select(x => init(x)).ToList();
		public static T[,] Array2<T>(int n, int m, T init)
		{
			var array = new T[n, m];
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					array[i, j] = init;
				}
			}

			return array;
		}

		public static T[,] Array2<T>(int n, int m, Func<int, int, T> initializer)
		{
			var array = new T[n, m];
			for (int i = 0; i < n; i++) {
				for (int j = 0; j < m; j++) {
					array[i, j] = initializer(i, j);
				}
			}

			return array;
		}

		public static T[,,] Array3<T>(int n1, int n2, int n3, T init)
		{
			var array = new T[n1, n2, n3];
			for (int i1 = 0; i1 < n1; i1++) {
				for (int i2 = 0; i2 < n2; i2++) {
					for (int i3 = 0; i3 < n3; i3++) {
						array[i1, i2, i3] = init;
					}
				}
			}

			return array;
		}

		private static readonly int[] delta4_ = { 1, 0, -1, 0, 1 };
		[MethodImpl(MethodImplOptions.AggressiveInlining)]
		public static void DoAt4(int i, int j, int imax, int jmax, Action<int, int> action)
		{
			for (int dn = 0; dn < 4; dn++) {
				int d4i = i + delta4_[dn];
				int d4j = j + delta4_[dn + 1];
				if ((uint)d4i < (uint)imax && (uint)d4j < (uint)jmax) {
					action(d4i, d4j);
				}
			}
		}
	}

	public class Scanner
	{
		private readonly char[] delimiter_ = new char[] { ' ' };
		private readonly string filePath_;
		private readonly Func<string> reader_;
		private string[] buf_;
		private int index_;

		public Scanner(string file = "")
		{
			if (string.IsNullOrWhiteSpace(file)) {
				reader_ = Console.ReadLine;
			} else {
				filePath_ = file;
				var fs = new StreamReader(file);
				reader_ = fs.ReadLine;
			}
			buf_ = new string[0];
			index_ = 0;
		}

		public string NextLine() => reader_();
		public string Next()
		{
			if (index_ < buf_.Length) {
				return buf_[index_++];
			}

			string st = reader_();
			while (st == "") {
				st = reader_();
			}

			buf_ = st.Split(delimiter_, StringSplitOptions.RemoveEmptyEntries);
			if (buf_.Length == 0) {
				return Next();
			}

			index_ = 0;
			return buf_[index_++];
		}

		public int Int() => int.Parse(Next());
		public long Long() => long.Parse(Next());
		public double Double() => double.Parse(Next());

		public int[] ArrayInt(int N, int add = 0)
		{
			int[] Array = new int[N];
			for (int i = 0; i < N; i++) {
				Array[i] = Int() + add;
			}
			return Array;
		}

		public long[] ArrayLong(int N, long add = 0)
		{
			long[] Array = new long[N];
			for (int i = 0; i < N; i++) {
				Array[i] = Long() + add;
			}
			return Array;
		}

		public double[] ArrayDouble(int N, double add = 0)
		{
			double[] Array = new double[N];
			for (int i = 0; i < N; i++) {
				Array[i] = Double() + add;
			}
			return Array;
		}

		public void Save(string text)
		{
			if (string.IsNullOrWhiteSpace(filePath_)) {
				return;
			}

			File.WriteAllText(filePath_ + "_output.txt", text);
		}
	}
}