#include <bits/stdc++.h>

using namespace std;
using uint = unsigned int;
using ll = long long;
using ull = unsigned long long;
template<class T> using V = vector<T>;
template<class T> using VV = V<V<T>>;
constexpr ll TEN(int n) { return (n == 0) ? 1 : 10 * TEN(n-1); }

template <class T> ostream& operator<<(ostream& os, const V<T>& v) {
    os << "[";
    for (auto d : v) os << d << ", ";
    return os << "]";
}

template <class T, class U>
ostream& operator<<(ostream& os, const pair<T, U>& p) {
    return os << "P(" << p.first << ", " << p.second << ")";
}

uint MD;
struct ModInt {
    using M = ModInt;
    uint v;
    ModInt() : v(0) {}
    ModInt(ll _v) { set_v(_v % MD + MD); }
    M& set_v(uint _v) {
        v = (_v < MD) ? _v : _v - MD;
        return *this;
    }
    explicit operator bool() const { return v != 0; }
    M operator-() const { return M() - *this; }
    M operator+(const M& r) const { return M().set_v(v + r.v); }
    M operator-(const M& r) const { return M().set_v(v + MD - r.v); }
    M operator*(const M& r) const { return M().set_v(ull(v) * r.v % MD); }
    M operator/(const M& r) const { return *this * r.inv(); }
    M& operator+=(const M& r) { return *this = *this + r; }
    M& operator-=(const M& r) { return *this = *this - r; }
    M& operator*=(const M& r) { return *this = *this * r; }
    M& operator/=(const M& r) { return *this = *this / r; }
    M pow(ll n) const {
        M x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    M inv() const { return pow(MD - 2); }
    friend ostream& operator<<(ostream& os, const M& r) { return os << r.v; }
};
using Mint = ModInt;


template <class N, class E> struct AllTree {
    int n;
    const VV<E>& g;
    V<N> sm;
    VV<N> dp;
    void dfs1(int p, int b) {
        sm[p] = N();
        for (auto e : g[p]) {
            int d = e.to;
            if (d == b) continue;
            dfs1(d, p);
            sm[p] = sm[p] + sm[d].first(p, e);
        }
        sm[p].finish(p);
    }
    void dfs2(int p, int b, N top) {
        int deg = int(g[p].size());
        dp[p] = V<N>(deg + 1);
        dp[p][0] = N();
        for (int i = 0; i < deg; i++) {
            int d = g[p][i].to;
            dp[p][i + 1] = dp[p][i] + (d == b ? top : sm[d]).first(p, g[p][i]);
        }
        N rnode = N();
        for (int i = deg - 1; i >= 0; i--) {
            int d = g[p][i].to;
            if (d != b) {
                dfs2(d, p, (dp[p][i] + rnode).finish(p));
            }
            dp[p][i] = dp[p][i] + rnode;
            rnode = rnode + (d == b ? top : sm[d]).first(p, g[p][i]);
        }
    }
    AllTree(const VV<E>& _g) : n(int(_g.size())), g(_g), sm(n), dp(n) {
        dfs1(0, -1);
        dfs2(0, -1, N());
    }
};
template <class N, class E> VV<N> get_all_tree(const VV<E>& g) {
    return AllTree<N, E>(g).dp;
}

struct Node {
    // サンプル 木の直径
    // firstは 根付き木->森
    // finishは森->根付き木
    Mint sm = Mint(0);
    Node() {
        // !!!!!森を生成すること!!!!!
        sm = 1;
    }
    template <class E> Node first(int, const E&) const {
        // 根付き木->森 上に辺を追加するイメージ e=(par -> node)
        Node n = *this;
        n.sm += Mint(1);
        return n;
    }
    Node operator+(const Node& r) const {
        // 結合則が必須 上に辺を追加された木をまとめるイメージ
        Node n;
        n.sm = sm * r.sm;
        return n;
    }
    Node finish(int) {
        // 元締めとしてidxを追加するイメージ
        return *this;
    }
    friend ostream& operator<<(ostream& os, const Node& r) { return os << r.sm; }
};

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);

    int n;
    cin >> n >> MD;
    struct E { int to; };
    VV<E> g(n);
    for (int i = 0; i < n-1; i++) {
        int a, b;
        cin >> a >> b; a--; b--;
        g[a].push_back(E{b});
        g[b].push_back(E{a});
    }

    auto all_tree = get_all_tree<Node>(g);

    for (int i = 0; i < n; i++) {
        cout << all_tree[i].back().sm << "\n";
    }
    return 0;
}


Measured memory_bytes: 17660