#include <bits/stdc++.h>

using namespace std;

using ll = long long;

class UnionFind {
  vector<ll> par, h;
public:
  UnionFind(ll size) : par(size, 0), h(size, 0) {
    for (int i = 0; i < size; ++i) {
      par[i] = i;
    }
  }
  void unite(ll u, ll v) {
    u = root(u), v = root(v);
    if (u == v) return;
    if (h[u] < h[v]) {
      par[u] = v;
    }
    else {
      par[v] = u;
    }
    if (h[u] == h[v]) ++h[u];
  }
  bool isUnited(ll u, ll v) {
    return root(u) == root(v);
  }
  ll root(ll v) {
    if (par[v] == v) return v;
    return par[v] = root(par[v]);
  }
};

template<typename Weight, typename Value>
struct DpEdge {
  ll to, rev;
  Weight weight;
  Value value;
};

template<class Calc>
class EdgeDpOnForest {
public:
  using T = typename Calc::type;
  using Weight = typename Calc::edge_type;
  using Edge = DpEdge<Weight, T>;
private:
  ll n;
  void dfs1(ll v, ll pv) {
    ll idx = -1;
    vector<Edge> edges;
    for (int i = 0; i < G[v].size(); ++i) {
      const Edge& e = G[v][i];
      if (e.to == pv) {
        idx = i;
        continue;
      }
      dfs1(e.to, v);
      edges.push_back(e);
    }
    // 根以外では親から入る辺の値を更新
    if (idx >= 0) {
      const Edge& e = G[v][idx];
      G[e.to][e.rev].value = Calc::merge(edges, G[v][idx]);
    }
  }
  void dfs2(ll v, ll pv) {
    vector<T> values = Calc::evaluate(G[v], v);
    for (int i = 0; i < G[v].size(); ++i) {
      const Edge& e = G[v][i];
      if (e.to == pv) continue;
      G[e.to][e.rev].value = values[i];
      dfs2(e.to, v);
    }
  }
public:
  UnionFind uf;
  vector<vector<Edge>> G;
  EdgeDpOnForest(ll n) : n(n), uf(n), G(n) {}
  void add(ll u, ll v, Weight w) {
    assert(!uf.isUnited(u, v));
    G[u].push_back({v, ll(G[v].size()), w});
    G[v].push_back({u, ll(G[u].size())-1, w});
    uf.unite(u, v);
  }
  void dp() {
    vector<bool> used(n, false);
    for (int i = 0; i < n; ++i) {
      if (used[uf.root(i)]) continue;
      dfs1(i, -1);
      used[uf.root(i)] = true;
    }
    used.assign(n, false);
    for (int i = 0; i < n; ++i) {
      if (used[uf.root(i)]) continue;
      dfs2(i, -1);
      used[uf.root(i)] = true;
    }
  }
  size_t size() const {
    return G.size();
  }
};

ll M;

struct Merger {
  using type = ll;
  using edge_type = ll;
  using Edge = DpEdge<type, edge_type>;
  // その頂点から出ていく値から入ってくる値を計算する
  static vector<type> evaluate(const vector<Edge>& edges, const ll node_id) {
    const ll n = edges.size();
    vector<type> L(n+1, 1), R(n+1, 1);
    for (int i = 0; i < n; ++i) {
      L[i+1] = (L[i] * edges[i].value) % M;
      R[n-i-1] = (R[n-i] * edges[n-i-1].value) % M;
    }
    vector<type> res(n);
    for (int i = 0; i < n; ++i) {
      res[i] = (L[i] * R[i+1] + 1) % M;
    }
    return res;
  }
  // (辺数-1)個の出ていく値から1個の入ってくる値を計算する
  static type merge(const vector<Edge>& edges, const Edge& e) {
    type res = 1;
    for (auto&& e : edges) {
      res = (res * e.value) % M;
    }
    res = (res + 1) % M;
    return res;
  }
};

int main() {
  ll n; cin >> n >> M;
  EdgeDpOnForest<Merger> dp(n);
  for (int i = 0; i < n-1; ++i) {
    ll a, b; cin >> a >> b; --a, --b;
    dp.add(a, b, 0);
  }
  dp.dp();
  for (int i = 0; i < n; ++i) {
    ll ans = 1;
    for (auto&& e : dp.G[i]) {
      ans = (ans * e.value) % M;
    }
    cout << ans << endl;
  }
}


Measured memory_bytes: 21120