#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mem(a, b) memset(a,b,sizeof(a))
#define INF 0x3f3f3f3f
#define DBG printf("this is a input\n")
#define fi first
#define se second
#define mk(a, b) make_pair(a,b)
#define p_queue priority_queue
ll gcd(ll a, ll b) {
return b == 0 ? a : gcd(b, a % b);
}
ll lcm(ll a, ll b) {
return a / gcd(a, b) * b;
}
int n , m, vis[200005];
int head[200005], cnt;
struct e{
int t, next;
}edge[200005];
struct question
{
int x, y ,z;
}qes[200005];
void add(int f, int t)
{
edge[cnt].t =t ;
edge[cnt].next = head[f];
head[f] = cnt ++;
}
int bz[100005][30] , dep[100005];
int idx[100005];
void dfs(int u, int deep)
{
dep[u] = deep;
for(int i = head[u] ; i != -1 ; i = edge[i].next) {
int v = edge[i].t;
if (!dep[v]){
bz[v][0] = u;
dfs(v, deep+1);
}
}
}
void deal()
{
for(int i = 1 ; i <= 25 ; i ++)
for(int j = 1 ; j <= n ; j ++)
bz[j][i] = bz[bz[j][i-1]][i-1];
}
int LCA(int x, int y)
{
if(dep[x] < dep[y])
swap(x,y);
for(int i = 25 ; i >= 0 ; i --)
if(dep[bz[x][i]] >= dep[y])
x = bz[x][i];
if (x == y)
return x;
for(int i = 25 ; i >= 0 ; i --)
{
if(bz[x][i] ^ bz[y][i])
x = bz[x][i] , y = bz[y][i];
}
return bz[x][0];
}
int rt[200005], ans[200005];
int tot, len;
struct sg{
int lc, rc, mx ,id;
}tree[200005*80];
void pushup(int id)
{
int lc = tree[id].lc, rc = tree[id].rc;
if(tree[lc].mx >= tree[rc].mx) tree[id].mx = tree[lc].mx, tree[id].id = tree[lc].id;
else tree[id].mx = tree[rc].mx , tree[id].id = tree[rc].id;
}
void update(int &id, int l ,int r, int val, int c)
{
if (!id) id = ++ tot;//动态编号,类似主席树
if(l == r) {
tree[id].mx += c, tree[id].id = l;
return ;
}
int mid = (l + r) >> 1;
//这里是动态开点,每次只会执行一半
if(val <= mid) update(tree[id].lc,l,mid,val,c);
else update(tree[id].rc,mid+1,r,val,c);
pushup(id);
}
int merge(int x , int y, int l , int r)
{
//这里是区间合并,把深度大的朝小的合并,前缀和思想
if(!x) return y;
if(!y) return x;
if(l == r){
tree[x].mx += tree[y].mx;
return x;
}
int mid = (l + r) >> 1;
tree[x].lc = merge(tree[x].lc , tree[y].lc , l ,mid);
tree[x].rc = merge(tree[x].rc , tree[y].rc , mid+1 , r);
pushup(x);
return x;
}
void getans(int u)
{
vis[u] = 1;
for(int i = head[u] ; i != -1; i = edge[i].next)
{
int v = edge[i].t;
if(!vis[v])
{
getans(v);
rt[u] = merge(rt[u], rt[v], 1, len);
}
}
ans[u] = tree[rt[u]].mx == 0 ? 0 : tree[rt[u]].id;
}
int main(void)
{
mem(head,-1);
scanf("%d %d",&n,&m);
int u , v , z;
for(int i = 1 ; i < n ; i ++)
{
scanf("%d %d",&u,&v);
add(u,v);
add(v,u);
}
dfs(1,1);
deal();
for(int i = 1 ; i <= m ; i ++)
scanf("%d %d %d",&qes[i].x,&qes[i].y,&qes[i].z), idx[i] = qes[i].z;
//对救济种类离散化
sort(idx+1,idx+1+m);
len = unique(idx+1,idx+1+m)-idx-1;
//树上差分经典操作
//每一个树上节点都开一颗权值线段树,权值线段树用于维护差分数组
//由于采用动态开点,所以每一颗线段树的空间为LogN,遍历复杂度也为LogN
for(int i = 1 ; i <= m ; i ++)
{
u = qes[i].x , v = qes[i].y, z = qes[i].z;
int lca = LCA(u,v);
int zt = lower_bound(idx+1,idx+1+len,z)-idx;
update(rt[u],1,len,zt,1);
update(rt[v],1,len,zt,1);
update(rt[lca],1,len,zt,-1);
update(rt[bz[lca][0]],1,len,zt,-1);
}
//树上差分获得序列的基本操作,这里是权值线段树的合并
getans(1);
for(int i = 1 ; i <= n ; i ++)
printf("%d\n",idx[ans[i]]);
}