// Slower C++ solution:
#include <iostream>

#include <math.h>

#include <queue>

#include <algorithm>

#include <map>

#include <set>

#include <cstdlib>

#include <unordered_map>

#include <numeric>



using namespace std;



#define fs first

#define sc second



typedef long long ll;

typedef pair<int, int> P;



ll mod = 1e9+7;

ll fact[200200];

ll invfact[200200];



inline ll take_mod(ll a){

    return (a % mod + mod) % mod;

}



inline ll add(ll a, ll b){

    return take_mod(a+b);

}



inline ll sub(ll a, ll b){

    return take_mod(a-b);

}





inline ll mul(ll a, ll b){

    return take_mod(a * b);

}



inline ll pow(ll x, ll n){

    ll res = 1LL;

    while(n > 0){

        if(n & 1) res = mul(res, x);

        x = mul(x, x);

        n >>= 1;

    }

    return res;

}



ll mod_inv(ll x){

    return pow(x, mod-2);

}



// nは上限

void make_fact(ll n){

    fact[0] = 1;

    ll res = 1;

    for(int i = 1; i <= n; i++){

        fact[i] = res;

        res = mul(res, i+1);

    }

}



// nは上限

void make_invfact(ll n){

    invfact[0] = 1;

    invfact[n] = mod_inv(fact[n]);

    for(int i = n-1; i >= 1; i--){

        invfact[i] = mul(invfact[i + 1], i + 1);

    }

}



ll perm(ll n, ll k){

    return mul(fact[n], invfact[n-k]);

}



ll comb(ll n, ll k){

    return mul(mul(fact[n], invfact[n-k]), invfact[k]);

}



vector<int> edge[101000];

ll stateNum1[101000];

ll stateNum2[101000];



ll dfs1(int s, int prev){

    ll res = 1;  // 自分が黒に塗られた場合

    for(auto v: edge[s]){

        if(v == prev){

            continue;

        }

        res = mul(res, dfs1(v, s));

    }

    res = add(res, 1);   // 自分が塗られない場合を足す。

    stateNum1[s] = res;

    return res;

}



void dfs2(int s, int prev, ll prevState){

    int n = edge[s].size();



    ll *hist1;

    ll *hist2;

    hist1 = new ll[n+2];   // i番目より前

    hist2 = new ll[n+2];   // i番目より後

    hist1[0] = 1;



    for(int i = 0; i < n-1; i++){

        int v = edge[s][i];

        ll tmp;

        if(v == prev) {

            tmp = mul(hist1[i], prevState);

        }

        else{

            tmp = mul(hist1[i], stateNum1[v]);

        }

        hist1[i+1] = tmp;

    }



    hist2[n-1] = 1;

    for(int i = n-2; i >= 0; i--){

        int v = edge[s][i+1];

        ll tmp;

        if(v == prev) {

            tmp = mul(hist2[i+1], prevState);

        }

        else{

            tmp = mul(hist2[i+1], stateNum1[v]);

        }

        hist2[i] = tmp;

    }

//    for(int i = 0; i < n; i++){

//        cout << s << " " << hist1[i] << " " << hist2[i] << endl;

//    }



    ll res = 1;

    for(auto v: edge[s]){

        if(v == prev){

            res = mul(res, prevState);

        }

        else{

            res = mul(res, stateNum1[v]);

        }

    }

    stateNum2[s] = res;

    for(int i = 0; i < n; i++){

        int v = edge[s][i];

        if(v == prev){

            continue;

        }

        ll newPrevState = add(mul(hist1[i], hist2[i]), 1);

        dfs2(v, s, newPrevState);

    }

    delete[] hist1;

    delete[] hist2;

}





int main(){

    ll N, M;

    cin >> N >> M;

    mod = M;

    for(int i = 0; i < N-1; i++){

        int x, y;

        cin >> x >> y;

        x--; y--;

        edge[x].push_back(y);

        edge[y].push_back(x);

    }



    if(N == 1){

        cout << 1 << endl;

        return 0;

    }

    dfs1(0, 0);

    dfs2(0, 0, 0);

//    for(int i = 0; i < N; i++){

//        cout << stateNum1[i] << endl;

//    }

    for(int i = 0; i < N; i++){

        cout << stateNum2[i] << endl;

    }



    return 0;

}

// Faster C++ solution for the same problem (measured speedup: 3.5161046481768308x):
#include <iostream>

#include <vector>

#include <map>

#include <unordered_map>

#include <queue>

#include <set>

#include <algorithm>

#include <string>

#include <math.h>

#include <limits.h>

#include <stack>

#include <complex>

#include <stdlib.h>

#include <stdio.h>

#include <functional>

#include <cfloat>

#include <math.h>

#include <numeric>

#include <string.h>

#include <sys/time.h>

#include <random>





#define fs first

#define sc second

#define endl "\n"



using namespace std;



typedef long long ll;

typedef unsigned int uint;

typedef pair<ll, ll> P;



ll mod;



class modInt{

    ll value;



public:

    modInt(ll x=0): value{x % mod}{}



    inline modInt& operator+=(modInt x){

        value = (value + x.value) % mod;

        return *this;

    }



    inline modInt& operator-=(modInt x){

        value = (value + mod - x.value) % mod;

        return *this;

    }



    inline modInt& operator*=(modInt x){

        value = (value * x.value) % mod;

        return *this;

    }





    inline modInt operator/=(modInt x){

        *this *= x.inv();

        return *this;

    }



    inline modInt pow(modInt x, int n){

        modInt res = modInt(1LL);

        while(n > 0){

            if(n & 1)   res *= x;

            x *= x;

            n >>= 1;

        }

        return res;

    }



    inline modInt inv(){

        modInt res = pow(value, mod-2);

        return res;

    }



    inline ll get(){

        return value;

    }

};



modInt operator+(modInt x, modInt y){

    return x += y;

}



modInt operator-(modInt x, modInt y){

    return x -= y;

}



modInt operator*(modInt x, modInt y){

    return x *= y;

}



modInt operator/(modInt x, modInt y){

    return x /= y;

}



ostream& operator<<(ostream& os, modInt x){

    return os << x.get();

}





class modIntCombinations{

    vector<modInt> factArray;



    void make_fact(ll x){

        for(auto i = factArray.size(); i <= x+1; i++){

            modInt y = factArray[i-1] * i;

            factArray.push_back(y);

        }

    }



public:

    modIntCombinations(){

        factArray.emplace_back(1);

    }



    modInt fact(ll x){

        if(factArray.size() < x+1){

            make_fact(x);

        }

        return factArray[x];

    }



    modInt comb(ll n, ll k){

        if(n < k){

            return modInt{0};

        }

        else{

            return fact(n) / fact(k) / fact(n - k);

        }

    }



    modInt perm(ll n, ll k){

        if(n < k){

            return modInt{0};

        }

        else{

            return fact(n) / fact(k);

        }

    }

};



class Graph{

    struct edge{

        int vertice;

        ll weight;

    };



    vector<vector<edge>> g;

    unsigned int n;



public:

    Graph(unsigned int n): n{n}{

        g.resize(n);

    }



    void add_edge(int u, int v){

        g[u].emplace_back(edge{v, 1});

    };



    void add_edge(int u, int v, ll w){

        g[u].emplace_back(edge{v, w});

    }



    vector<edge>& get_edge(int v){

        return g[v];

    }



    unsigned int size(){

        return n;

    }



    vector<edge>& operator[](int v){

        return get_edge(v);

    }

};







template <typename T>

class ReRooting{

private:

    using Operate = function<T(T, T)>;  // monoid

    using OperateNode = function<T(T, int)>;



    Graph g;

    Operate merge;

    T u;                 // Operateについての単位元

    OperateNode f1, f2;



    vector<vector<T>> dp;

    vector<T> res;



    T dfs1(int v, int prev){

        T res = u;

        for(int i = 0; i < g[v].size(); i++){

            auto e = g[v][i];

            if(e.vertice == prev)   continue;

            dp[v][i] = dfs1(e.vertice, v);

            res = merge(res, f1(dp[v][i], e.vertice));

        }



        return f2(res, v);

    }



    void dfs2(int v, int prev, T fromP){

        int n = g[v].size();        // vからの辺を持つ頂点数

        for(int i = 0; i < n; i++){

            auto e = g[v][i];

            if(e.vertice == prev){

                dp[v][i] = fromP;

                break;

            }

        }



        vector<T> cumFromLeft(n + 1), cumFromRight(n + 1);

        cumFromLeft[0] = u; cumFromRight[n] = u;

        for(int i = 0; i < n; i++){

            cumFromLeft[i+1] = merge(cumFromLeft[i], f1(dp[v][i], v));

        }

        for(int i = n-1; i >= 0; i--){

            cumFromRight[i] = merge(cumFromRight[i+1], f1(dp[v][i], v));

        }



        for(int i = 0; i < n; i++){

            auto e = g[v][i];

            if(e.vertice == prev)   continue;

            T fromC = f2(merge(cumFromLeft[i], cumFromRight[i+1]), v);

            dfs2(e.vertice, v, fromC);

        }



        res[v] = f2(cumFromLeft[n], v);

    }





public:

    ReRooting(Graph& g_, Operate merge_, T u_, OperateNode f1_, OperateNode f2_):

            g(g_), merge(merge_), u(u_), f1(f1_), f2(f2_){

        dp.resize(g.size());

        for(int i = 0; i < g.size(); i++){

            dp[i].resize(g[i].size());

        }

        res.resize(g.size());

    }



    void calc(int root = 0){

        dfs1(root, root);

        dfs2(root, root, u);

    }



    T get(int v){

        return res[v];

    }

};





int main(){

    int n, m;

    cin >> n >> m;

    mod = m;



    Graph g(n);

    for(int i = 0; i < n-1; i++){

        int x, y;   cin >> x >> y;

        x--; y--;

        g.add_edge(x, y);

        g.add_edge(y, x);

    }



    ReRooting<modInt> reroot(g, [](modInt x, modInt y){ return x * y; }, modInt{1},

                            [](modInt x, int v) { return x+1; }, [](modInt x, int v) { return x; });

    reroot.calc(0);

    for(int i = 0; i < n; i++){

        cout << reroot.get(i) << endl;

    }



    return 0;

}