#![allow(unused_macros)]
#![allow(dead_code)]
#![allow(unused_imports)]

use text_io::*;

fn main() {
    const U_INF: usize = 1 << 60;
    const I_INF: isize = 1 << 60;

    //ただの頂点の受け取り。O(2(n-1))
    let n: usize = read!();
    let mut vertexes = vec![vec![]; n];
    for _ in 1..n {
        let mut xi: usize = read!();
        let mut yi: usize = read!();
        xi -= 1;
        yi -= 1;
        vertexes[xi].push(yi);
        vertexes[yi].push(xi);
    }

    let mut dp = vec![vec![None; 2]; n + 10];

    //頂点0に対して色が白黒2通りあるのでループ
    println!(
        "{}",
        solve(0, U_INF, 0, &vertexes, &mut dp) + solve(0, U_INF, 1, &vertexes, &mut dp)
    );
}

fn solve(
    now: usize,
    parent: usize,
    color: usize,
    vertexes: &Vec<Vec<usize>>,
    dp: &mut Vec<Vec<Option<ModUsize>>>,
) -> ModUsize {
    match dp[now][color] {
        Some(t) => t,
        None => {
            let mut cnt = ModUsize::new(1);
            //今の色に応じて白だけor白と黒両方見る
            let next_colors = if color == 1 { &[0][..] } else { &[0, 1][..] };
            //今の頂点とつながっている頂点のうち親でないもの全てに対して
            for &v in &vertexes[now] {
                if v == parent {
                    continue;
                } else {
                    let mut tmp = ModUsize::new(0);
                    //再帰
                    for &c in next_colors {
                        tmp += solve(v, now, c, vertexes, dp);
                    }
                    cnt *= tmp;
                }
            }
            dp[now][color] = Some(cnt);
            cnt
        }
    }
}

use num_integer::Integer;
use smallvec::alloc::fmt::{Display, Formatter};
use std::fmt;
use std::ops::{Add, AddAssign, Div, DivAssign, Mul, MulAssign, Sub, SubAssign};

#[derive(Copy, Clone)]
pub struct ModUsize {
    pub mod_value: usize,
    pub value: usize,
}

impl ModUsize {
    pub fn new(n: usize) -> Self {
        Self {
            mod_value: Self::mod1(),
            value: n % Self::mod1(),
        }
    }

    pub fn pow(self, n: usize) -> Self {
        if n == 0 {
            Self::new(1)
        } else if n % 2 == 0 {
            let t = self.pow(n / 2);
            t * t
        } else {
            self * self.pow(n - 1)
        }
    }

    pub fn inv(self) -> Self {
        self.pow(self.mod_value - 2)
    }

    pub fn mod1() -> usize {
        1000000007
    }

    pub fn mod2() -> usize {
        998244353
    }
}

impl Add for ModUsize {
    type Output = ModUsize;

    fn add(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        tmp.value += rhs.value;
        if tmp.value >= self.mod_value {
            tmp.value -= self.mod_value;
        }
        tmp
    }
}

impl AddAssign for ModUsize {
    fn add_assign(&mut self, rhs: Self) {
        *self = *self + rhs;
    }
}

impl Sub for ModUsize {
    type Output = ModUsize;

    fn sub(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        if tmp.value < rhs.value {
            tmp.value += self.mod_value;
        }
        tmp.value -= rhs.value;
        tmp
    }
}

impl SubAssign for ModUsize {
    fn sub_assign(&mut self, rhs: Self) {
        *self = *self - rhs;
    }
}

impl Mul for ModUsize {
    type Output = ModUsize;

    fn mul(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        tmp.value *= rhs.value;
        tmp.value %= self.mod_value;
        tmp
    }
}

impl MulAssign for ModUsize {
    fn mul_assign(&mut self, rhs: Self) {
        *self = *self * rhs;
    }
}

impl Div for ModUsize {
    type Output = ModUsize;

    fn div(self, rhs: Self) -> Self::Output {
        let mut tmp = self;
        tmp.value /= rhs.value;
        tmp.value %= self.mod_value;
        tmp
    }
}

impl DivAssign for ModUsize {
    fn div_assign(&mut self, rhs: Self) {
        *self = *self / rhs;
    }
}

impl Display for ModUsize {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "{}", self.value)
    }
}


Measured memory_bytes: 27136