import std.stdio, std.conv, std.string, std.bigint;
import std.math, std.random, std.datetime;
import std.array, std.range, std.algorithm, std.container, std.format;
string read(){ static string[] ss; while(!ss.length) ss = readln.chomp.split; string res = ss[0]; ss.popFront; return res; }

/*

木DP 数え上げ
----------------------------------------

そのノードを黒にしたときの、そのノード以下の塗り分けの総数 Node.b
そのノードを白にしたときの、そのノード以下の塗り分けの総数 Node.w

黒が続いてはいけないので、
Node.b は子ノードたちの Node.w の積
Node.w は子ノードたちの(Node.w + Node.b)の積


nd.b = prod(kid; nd.kids)(kid.w)
nd.w = prod(kid; nd.kids)(kid.w + kid.b)

求めるものは root.b + root.w

----------------------------------------

*/

const long mod = 1_000_000_007;

class Node{
	long _b, _w;
	int id;
	Node[] nodes;
	Node[] kids;
	Node parent;
	bool isVisited;
	this(int id){
		this.id = id;
	}
	void treefy(Node parent){
		this.parent = parent;
		foreach(nd; nodes) if(!parent || nd.id != parent.id) this.kids ~= nd, nd.treefy(this);
	}
	long black(){
		if(_b == 0){
			_b = 1;
			foreach(kid; kids) _b *= kid.white, _b %= mod;
		}
	 return _b;
	}
	long white(){
		if(_w == 0){
			_w = 1;
			foreach(kid; kids) _w *= (kid.white + kid.black), _w %= mod;
		}
		return _w;
	}
	override string toString(){
		return "id:" ~ id.to!string ~ " b:" ~ _b.to!string ~ " w:" ~ _w.to!string ~ " kids:" ~ kids.map!(x => x.id).to!string;
	}
}

void main(){
 int n = read.to!int;
 
 Node[] nodes;
 foreach(i; 0 .. n) nodes ~= new Node(i);
 
 foreach(i; 0 .. n - 1){
	 int x = read.to!int - 1;
	 int y = read.to!int - 1;
	 nodes[x].nodes ~= nodes[y];
	 nodes[y].nodes ~= nodes[x];
 }
 
 nodes[0].treefy(null);
	
	debug writeln("nodes:", nodes);
 
 (nodes[0].black + nodes[0].white).writeln;
}
