#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;
}


Measured memory_bytes: 47872