#include <iostream>
#include <vector>
#include <functional>

template <class T>
struct Edge {
    int from, to;
    T cost;
    Edge(int from = -1, int to = -1, T cost = 1) : from(from), to(to), cost(cost){};

    bool operator<(const Edge<T>& e) const { return this->cost < e.cost; }
    bool operator>(const Edge<T>& e) const { return this->cost > e.cost; }
};

template <class T = int>
class Graph {
public:
    explicit Graph(int N = 0) : size(N) { path.resize(size); }
    void span(int u, int v, T cost = 1) { path[u].push_back(Edge<T>(u, v, cost)); }
    std::vector<Edge<T>> operator[](int v) const { return path[v]; }

    int size;
    std::vector<std::vector<Edge<T>>> path;
};

class ModInt {
    using ll = long long;

public:
    int value;
    static int MOD;

    ModInt(ll value = 0) {
        this->value = (-MOD < value && value < MOD ? value : value % MOD);
        if (this->value < 0) this->value += MOD;
    }

    operator int() const noexcept { return this->value; }
    operator ll() const noexcept { return this->value; }

    ModInt& operator=(const ModInt& x) {
        if (this != &x) { this->value = x.value; }
        return *this;
    }

    bool operator==(const ModInt& x) const { return this->value == x.value; }
    bool operator!=(const ModInt& x) const { return !(*this == x); }

    ModInt operator+() const { return value; }
    ModInt operator-() const { return MOD - value; }
    ModInt operator~() const { return (*this) ^ ModInt(MOD - 2); }

    ModInt operator++() { return *this += 1; }
    ModInt operator--() { return *this -= 1; }

    ModInt operator++(int) {
        ModInt before = *this;
        ++(*this);
        return before;
    }
    ModInt operator--(int) {
        ModInt before = *this;
        --(*this);
        return before;
    }

    ModInt& operator+=(const ModInt& x) {
        int sum = this->value + x.value;
        return *this = (sum < MOD ? sum : sum - MOD);
    }
    ModInt& operator-=(const ModInt& x) {
        int diff = this->value - x.value;
        return *this = (diff >= 0 ? diff : diff + MOD);
    }
    ModInt& operator+=(int x) { return *this += ModInt(x); }
    ModInt& operator-=(int x) { return *this -= ModInt(x); }

    template <class T>
    ModInt& operator*=(const T& x) { return *this = ll(this->value) * ll(x) % MOD; }
    template <class T>
    ModInt& operator/=(const T& x) { return *this = (this->value % int(x) == 0 ? ModInt(this->value / int(x)) : *this * ~ModInt(x)); }
    template <class T>
    ModInt& operator^=(const T& x) {
        int n = int(x);
        ModInt b = *this;
        *this = 1;
        while (n > 0) {
            if (n & 1) *this *= b;
            n >>= 1;
            b *= b;
        }
        return *this;
    }

    template <class T>
    ModInt operator+(const T& b) const { return ModInt(*this) += b; }
    template <class T>
    ModInt operator-(const T& b) const { return ModInt(*this) -= b; }
    template <class T>
    ModInt operator*(const T& b) const { return ModInt(*this) *= b; }
    template <class T>
    ModInt operator/(const T& b) const { return ModInt(*this) /= b; }
    template <class T>
    ModInt operator^(const T& b) const { return ModInt(*this) ^= b; }
};

std::ostream& operator<<(std::ostream& os, const ModInt& x) { return os << x.value; }
std::istream& operator>>(std::istream& is, ModInt& x) { return is >> x.value; }

int ModInt::MOD = 1000000007;

template <class Weight, class Data>
class ReRooting {
    using DataMerger = std::function<Data(Data, Data)>;
    using Promoter = std::function<Data(Data, Edge<Weight>)>;

public:
    Graph<Weight> tree;
    std::vector<Data> data;
    Data id;
    DataMerger merge;
    Promoter promote;

    ReRooting(const Graph<Weight>& tree, Data id, DataMerger merge, Promoter promote)
        : tree(tree), data(tree.size), id(id), merge(merge), promote(promote) {
        dfs(0, -1);
        edfs(0, -1, id);
    }

    // vを根とする部分木の解でdataを埋める
    Data dfs(int v, int r) {
        data[v] = id;
        for (const auto& e : tree[v]) {
            if (e.to == r) continue;
            data[v] = merge(data[v], promote(dfs(e.to, v), e));
        }
        return data[v];
    }

    // vを根とする木の解を求める
    void edfs(int v, int r, Data par_data) {
        int cnum = tree[v].size();  // vから伸びる辺の数

        std::vector<std::pair<Data, int>> child;
        child.emplace_back(id, 0);  // index合わせ
        for (const auto& e : tree[v]) {
            auto d = (e.to == r ? par_data : data[e.to]);
            child.emplace_back(promote(d, e), e.to);
        }

        std::vector<Data> lacc(cnum + 2), racc(cnum + 2);
        // 左から、右からの累積和
        lacc[0] = id;
        for (int i = 1; i <= cnum; ++i) {
            lacc[i] = merge(lacc[i - 1], child[i].first);
        }
        racc[cnum + 1] = id;
        for (int i = cnum; i >= 1; --i) {
            racc[i] = merge(racc[i + 1], child[i].first);
        }

        data[v] = lacc[cnum];  // 全体の累積和が答え

        for (int i = 1; i <= cnum; ++i) {
            if (child[i].second == r) continue;
            edfs(child[i].second, v, merge(lacc[i - 1], racc[i + 1]));
        }
    }
};

int main() {
    int N, M;
    std::cin >> N >> M;
    ModInt::MOD = M;

    Graph<> tree(N);
    for (int i = 0; i < N - 1; ++i) {
        int u, v;
        std::cin >> u >> v;
        --u, --v;
        tree.span(u, v);
        tree.span(v, u);
    }

    // Data    : パターン数
    // Merger  : 積 (id = 1)
    // Promoter: +1 (全部白のパターン)
    ReRooting<int, ModInt> dp(tree, ModInt(1),
                              [](ModInt a, ModInt b) { return a * b; },
                              [](ModInt a, Edge<int> e) { return a + 1; });

    for (auto a : dp.data) std::cout << a << std::endl;
    return 0;
}


Measured memory_bytes: 40064