#include <bits/stdc++.h>
using namespace std;
using int64 = long long;
constexpr int DEBUG = 0;
struct Edge {
  const int from, to, id;
  Edge(int from, int to, int id) : from(from), to(to), id(id) {}
};
constexpr int64 P = 998244353;
struct FiniteField {
 private:
  int64 x;
  static inline int64 Normalize(int64 x) {
    if (0 <= x && x < P) return x;
    x %= P;
    if (x < 0) x += P;
    return x;
  }

 public:
  FiniteField(int64 x) : x(Normalize(x)) {}
  FiniteField() : x(0) {}
  int64 Value() const { return x; }
  inline FiniteField operator+(FiniteField o) const {
    FiniteField r(*this);
    r += o;
    return r;
  }
  inline FiniteField operator-(FiniteField o) const {
    FiniteField r(*this);
    r -= o;
    return r;
  }
  inline FiniteField operator*(FiniteField o) const {
    FiniteField r(*this);
    r *= o;
    return r;
  }
  inline FiniteField operator/(FiniteField o) const {
    FiniteField r(*this);
    r /= o;
    return r;
  }
  inline void operator+=(FiniteField o) { x = (x + o.x) % P; }
  inline void operator-=(FiniteField o) { x = (x + P - o.x) % P; }
  inline void operator*=(FiniteField o) { x = (x * o.x) % P; }
  void operator/=(FiniteField o) {
    int64 p = P - 2;
    while (p) {
      if (p % 2) {
        *this *= o;
      }
      o *= o;
      p /= 2;
    }
  }
};
ostream& operator<<(ostream& s, const FiniteField& v) {
  s << v.Value();
  return s;
}
template <typename T>
vector<vector<T>> Make2DVector(int d1, int d2, T default_value) {
  return vector<vector<T>>(d1, vector<T>(d2, default_value));
}
int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  int n;
  cin >> n;
  vector<vector<Edge>> graph(n);
  for (int i = 0; i < n - 1; i++) {
    int from;
    int to;
    cin >> from >> to;
    from--;
    to--;
    graph[from].emplace_back(from, to, i);
    graph[to].emplace_back(to, from, i);
  }
  auto dp = Make2DVector(n, 3, FiniteField(0));
  function<void(int, int, int)> dfs_fn = [&](int v, int p, int p_edge_id) {
    int k = 0;
    vector<int> cs;
    for (const auto& edge : graph[v]) {
      if (edge.to == p) continue;
      dfs_fn(edge.to, v, edge.id);
      cs.push_back(edge.to);
      if (edge.id < p_edge_id) k++;
    }
    int d = cs.size();
    vector<FiniteField> l_xs(d + 1);
    l_xs[0] = 1;
    for (int i = 0; i < d; i++) {
      l_xs[i + 1] = l_xs[i] * (dp[cs[i]][0] + dp[cs[i]][1]);
    }
    vector<FiniteField> r_ys(d + 1);
    r_ys[d] = 1;
    for (int i = d - 1; i >= 0; i--) {
      r_ys[i] = r_ys[i + 1] * (dp[cs[i]][0] + dp[cs[i]][2]);
    }
    for (int i = 0; i < k; i++) {
      dp[v][0] += l_xs[i] * dp[cs[i]][2] * r_ys[i + 1];
    }
    dp[v][1] = l_xs[k] * r_ys[k];
    for (int i = k; i < d; i++) {
      dp[v][2] += l_xs[i] * dp[cs[i]][2] * r_ys[i + 1];
    }
    dp[v][2] += l_xs[d];
  };
  dfs_fn(0, -1, n);
  auto ans = dp[0][0] + dp[0][2];
  cout << ans << endl;
}
