#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5 , L = 20;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int u[N] , v[N] , e[N];
int to[N][L] , val[N][L];
int dep[N];

int node_for_edge[N];

vector < pair < int , int > > adj[N];

void dfs(int u , int p){
    to [u][0] = p;
    val[u][0] = 1;
    dep[u] = 1 + dep[p];

    for(pair < int , int > A : adj[u]){
            int v  = A.second;
            int edge_index = A.first;

            if(v == p)continue;

            node_for_edge[ edge_index ] = v;
            dfs(v , u);
    }
}

/// we try to find the LCA and we do updates on the way
void update_path(int u , int v , int new_val){
    if(u == v)return;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < L ; i ++){
            if(k & (1 << i)){
                    /// update
                    val[u][i] = max(val[u][i] , new_val);
                    u = to[u][i];
            }
    }

    if(u == v)return;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    /// update for u
                    val[u][i] = max(val[u][i] , new_val);
                    /// update for v
                    val[v][i] = max(val[v][i] , new_val);

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    /// update last 2 edges
    val[u][0] = max(val[u][0] , new_val);
    val[v][0] = max(val[v][0] , new_val);
}

int get_min_val(int u , int v){
    if(u == v)return 0;

    int ret = 2e9;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < k ; i ++){
            if(k & (1 << i)){
                    ret = min(ret , val[u][i]);
                    u = to[u][i];
            }
    }

    if(u == v)return ret;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    ret = min({ret , val[u][i] , val[v][i]});

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    return min({ ret , val[u][0] , val[v][0] });
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    dfs(1 , 0);

    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    to [i][j] =                   to [ to[i][j-1] ][j-1] ;
                    val[i][j] = max(val[i][j-1] , val[ to[i][j-1] ][j-1]);

                    //cout << val[i][j] << " ";
            }
    }
    //cout << endl;

    scanf("%d" , &m);

    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);

            update_path(u[i] , v[i] , e[i]);
    }

    /// after updates we push values from higher rows to lower rows
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
            }
    }

    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }
    /// after that all the values of the edges will be in val[i][0];

    /// then we initialize for minimum queries
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j] = min(val[i][j-1] , val[ to[i][j-1] ][j-1]);
            }
    }

    for(int i = 1 ; i <= m ; i ++){
            //cout << u[i] << " " << v[i] << " " << e[i] << " , " << get_min_val(u[i] , v[i]) << endl;
            if(get_min_val(u[i] , v[i]) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , val[ node_for_edge[i] ][0] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int to[N] , p[N] , w[N];
int  u[N] , v[N] , e[N];
int dep[N];

int segTreePos[N] , heavy[N] , chain[N];
int st[N << 2] , lazy[N << 2];

vii adj[N];

int dfs(int u , int pr){

    int sz = 1;
    int mx = 0;
    for(ii A : adj[u]){
            int v = A.second;
            int e = A.first;

            if(v == pr)continue;

            to[e] = v;
            p[v] = u;
            dep[v] = 1 + dep[u];
            int curr = dfs(v , u);
            sz += curr;
            if(curr > mx){
                    mx = curr;
                    heavy[u] = v;
            }
    }

    return sz;
}

void build_chains(){
    dfs(1 , 0);

    int pos = 0;

    for(int i = 1 ; i <= n ; i ++){
            if(p[i] == 0 || heavy[ p[i] ] !=  i){
                    for(int j = i ; j != 0 ; j = heavy[j]){
                            segTreePos[j] = ++ pos;
                            chain[j] = i;
                    }
            }
    }
}

void psh(int p , int l , int r){
    if(lazy[p] == 0)return;

    st[p] = max(st[p] , lazy[p]);

    if(l != r){
            lazy[p << 1]     = max(lazy[p << 1] , lazy[p]);
            lazy[p << 1 | 1] = max(lazy[p << 1 | 1] , lazy[p]);
    }

    lazy[p] = 0;
}

void update_range(int p , int l , int r , int S , int E , int val){
    psh(p , l , r);

    if(l >= S && r <= E){
            lazy[p] = val;
            psh(p , l , r);
            return;
    }
    if(l > E || r < S)return;

    int mid = (l + r) >> 1;

    update_range(p << 1 , l , mid , S , E , val);
    update_range(p << 1 | 1 , mid + 1 , r , S , E , val);

    st[p] = min(st[p << 1] , st[p << 1 | 1]);
}

int rmq(int p , int l , int r , int S , int E){
    psh(p , l , r);

    if(l >= S && r <= E)return st[p];
    if(l > E || r < S)  return 2e9;

    int mid = (l + r) >> 1;

    return min(rmq(p << 1 , l , mid , S , E) , rmq(p << 1 | 1 , mid + 1 , r , S , E));
}

int query(int u , int v){

    int ret = 2e9;
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            ret = min(ret , rmq(1 , 1 , n , segTreePos[ chain[u] ] , segTreePos[u]));
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            ret = min(ret , rmq(1 , 1 , n , l+1 , r));
    }

    return ret;
}

void update(int u , int v , int val){
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            update_range(1 , 1 , n , segTreePos[ chain[u] ] , segTreePos[u] , val);
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            update_range(1 , 1 , n , l+1 , r , val);
    }
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
            w[i] = 1;
    }

    build_chains();

    for(int i = 1 ; i < n ; i ++){
            update_range(1 , 1 , n , segTreePos[to[i]] , segTreePos[to[i]] , 1);
    }

    scanf("%d" , &m);
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update(u[i] , v[i] , e[i]);
    }

    for(int i = 1 ; i <= m ; i ++){
            if(query(u[i] , v[i]) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , rmq(1 , 1 , n , segTreePos[to[i]] , segTreePos[to[i]]) , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 3e5 + 5;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int to[N] , p[N];
int  u[N] , v[N] , e[N];
int dep[N];

int segTreePos[N] , heavy[N] , chain[N];
int st[N << 2] , lazy[N << 2];

vii adj[N];

int dfs_hld(int u){

    if(u != 1)dep[u] = 1 + dep[p[u]];

    int sz = 1;
    int mx = 0;///heavy child
    for(ii A : adj[u]){
        int v  = A.second;
        int dx = A.first;///edge index

        if(v == p[u])continue;

         p[v]  = u;
        to[dx] = v;///map this edge to node v
        int curr = dfs_hld(v);

        if(curr > mx){
            mx = curr;
            heavy[u] = v;
        }

        sz += curr;
    }

    return sz;
}

void build_chains(){

    dfs_hld(1);

    int pos = 0;///pos in segment tree

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

        if(chain[ chainRoot ] == -1 || heavy[ p[ chainRoot ] ] != chainRoot){

            for(int j = chainRoot ; j != -1 ; j = heavy[j]){

                chain[j] = chainRoot;
                segTreePos[j] = ++ pos;

            }

        }

    }
}

void psh(int p , int l , int r){
    if(lazy[p] == 0)return;

    st[p] = max(st[p] , lazy[p]);

    if(l != r){
            lazy[p << 1]     = max(lazy[p << 1]     , lazy[p]);
            lazy[p << 1 | 1] = max(lazy[p << 1 | 1] , lazy[p]);
    }

    lazy[p] = 0;
}

void update_range(int p , int l , int r , int S , int E , int val){
    psh(p , l , r);

    if(l >= S && r <= E){
            lazy[p] = max(lazy[p] , val);
            psh(p , l , r);
            return;
    }
    if(l > E || r < S)return;

    int mid = (l + r) >> 1;

    update_range(p << 1 , l , mid , S , E , val);
    update_range(p << 1 | 1 , mid + 1 , r , S , E , val);

    st[p] = min(st[p << 1] , st[p << 1 | 1]);
}

int rmq(int p , int l , int r , int S , int E){
    psh(p , l , r);

    if(l >= S && r <= E)return st[p];
    if(l > E || r < S)  return 2e9;

    int mid = (l + r) >> 1;

    return min(rmq(p << 1 , l , mid , S , E) , rmq(p << 1 | 1 , mid + 1 , r , S , E));
}

int query(int u , int v){

    int ret = 2e9;
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            ret = min(ret , rmq(1 , 1 , N-1 , segTreePos[ chain[u] ] , segTreePos[u]));
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            ret = min(ret , rmq(1 , 1 , N-1 , l+1 , r));
    }

    return ret;
}

void update(int u , int v , int val){
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            update_range(1 , 1 , N-1 , segTreePos[ chain[u] ] , segTreePos[u] , val);
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            update_range(1 , 1 , N-1 , l+1 , r , val);
    }
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            assert(u <= n);
            assert(v <= n);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    build_chains();

    for(int i = 1 ; i < n ; i ++){
            update_range(1 , 1 , N-1 , segTreePos[to[i]] , segTreePos[to[i]] , 1);
    }

    scanf("%d" , &m);
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update(u[i] , v[i] , e[i]);
    }

    for(int i = 1 ; i <= m ; i ++){
            int curr = query(u[i] , v[i]);

            if(curr != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            if(segTreePos[to[i]] > n){
                    cout << i << " " << to[i] << " " << segTreePos[to[i]] << endl;
                    assert(5 > 6);
            }
            int curr = rmq(1 , 1 , N-1 , segTreePos[to[i]] , segTreePos[to[i]]);
            if(curr == 2e9)curr = 1;
            printf("%d%c" , curr , i == n-1 ? '\n' : ' ');
    }

}

main(){

    memset(heavy , -1 , sizeof heavy);
    memset(chain , -1 , sizeof chain);
    memset(p     , -1 , sizeof p    );

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int to[N] , p[N] , w[N];
int  u[N] , v[N] , e[N];
int dep[N];

int segTreePos[N] , heavy[N] , chain[N];
int st[N << 2] , lazy[N << 2];

vii adj[N];

int dfs(int u , int pr){

    int sz = 1;
    int mx = 0;
    for(ii A : adj[u]){
            int v = A.second;
            int e = A.first;

            if(v == pr)continue;

            to[e] = v;
            p[v] = u;
            dep[v] = 1 + dep[u];
            int curr = dfs(v , u);
            sz += curr;
            if(curr > mx){
                    mx = curr;
                    heavy[u] = v;
            }
    }

    return sz;
}

void build_chains(){
    dfs(1 , 0);

    int pos = 0;

    for(int i = 1 ; i <= n ; i ++){
            if(chain[i] == 0 || heavy[ p[i] ] !=  i){
                    for(int j = i ; j != 0 ; j = heavy[j]){
                            segTreePos[j] = ++ pos;
                            chain[j] = i;
                    }
            }
    }
}

void psh(int p , int l , int r){
    if(lazy[p] == 0)return;

    st[p] = max(st[p] , lazy[p]);

    if(l != r){
            lazy[p << 1]     = max(lazy[p << 1] , lazy[p]);
            lazy[p << 1 | 1] = max(lazy[p << 1 | 1] , lazy[p]);
    }

    lazy[p] = 0;
}

void update_range(int p , int l , int r , int S , int E , int val){
    psh(p , l , r);

    if(l >= S && r <= E){
            lazy[p] = val;
            psh(p , l , r);
            return;
    }
    if(l > E || r < S)return;

    int mid = (l + r) >> 1;

    update_range(p << 1 , l , mid , S , E , val);
    update_range(p << 1 | 1 , mid + 1 , r , S , E , val);

    st[p] = min(st[p << 1] , st[p << 1 | 1]);
}

int rmq(int p , int l , int r , int S , int E){
    psh(p , l , r);

    if(l >= S && r <= E)return st[p];
    if(l > E || r < S)  return 2e9;

    int mid = (l + r) >> 1;

    return min(rmq(p << 1 , l , mid , S , E) , rmq(p << 1 | 1 , mid + 1 , r , S , E));
}

int query(int u , int v){

    int ret = 2e9;
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            ret = min(ret , rmq(1 , 1 , n , segTreePos[ chain[u] ] , segTreePos[u]));
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            ret = min(ret , rmq(1 , 1 , n , l+1 , r));
    }

    return ret;
}

void update(int u , int v , int val){
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            update_range(1 , 1 , n , segTreePos[ chain[u] ] , segTreePos[u] , val);
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            update_range(1 , 1 , n , l+1 , r , val);
    }
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
            w[i] = 1;
    }

    build_chains();

    for(int i = 1 ; i < n ; i ++){
            update_range(1 , 1 , n , segTreePos[to[i]] , segTreePos[to[i]] , 1);
    }

    scanf("%d" , &m);
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update(u[i] , v[i] , e[i]);
    }

    for(int i = 1 ; i <= m ; i ++){
            int curr = query(u[i] , v[i]);
            if(curr == 2e9)curr = 1;
            if(curr != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            int curr = rmq(1 , 1 , n , segTreePos[to[i]] , segTreePos[to[i]]);
            if(curr == 2e9)curr = 1;
            printf("%d%c" , curr , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5 , L = 20;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int u[N] , v[N] , e[N];
int to[N][L] , val[N][L];
int dep[N];

int node_for_edge[N];

vector < pair < int , int > > adj[N];

void dfs(int u , int p){
    to [u][0] = p;
    val[u][0] = 1;
    dep[u] = 1 + dep[p];

    for(pair < int , int > A : adj[u]){
            int v  = A.second;
            int edge_index = A.first;

            if(v == p)continue;

            node_for_edge[ edge_index ] = v;
            dfs(v , u);
    }
}

/// we try to find the LCA and we do updates on the way
void update_path(int u , int v , int new_val){
    if(u == v)return;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < L ; i ++){
            if(k & (1 << i)){
                    /// update
                    val[u][i] = max(val[u][i] , new_val);
                    u = to[u][i];
            }
    }

    if(u == v)return;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    /// update for u
                    val[u][i] = max(val[u][i] , new_val);
                    /// update for v
                    val[v][i] = max(val[v][i] , new_val);

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    /// update last 2 edges
    val[u][0] = max(val[u][0] , new_val);
    val[v][0] = max(val[v][0] , new_val);
}

int get_min_val(int u , int v){
    if(u == v)return 0;

    int ret = 2e9;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < k ; i ++){
            if(k & (1 << i)){
                    ret = min(ret , val[u][i]);
                    u = to[u][i];
            }
    }

    if(u == v)return ret;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    ret = min({ret , val[u][i] , val[v][i]});

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    return min({ ret , val[u][0] , val[v][0] });
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    dfs(1 , 0);

    /// build sparse table
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    to [i][j] =                   to [ to[i][j-1] ][j-1] ;
                    val[i][j] = max(val[i][j-1] , val[ to[i][j-1] ][j-1]);

                    //cout << val[i][j] << " ";
            }
    }
    //cout << endl;

    scanf("%d" , &m);

    /// take the queries and update values on paths
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update_path(u[i] , v[i] , e[i]);
    }

    /// after updates we push values from higher columns to lower columns
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }

    /*
    for(int i = 1 ; i <= n ; i ++){
            for(int j = L-1 ; j >= 1 ; j --){
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }
    */
    /// after that all the values of the edges will be in val[i][0];

    /// then we initialize for minimum queries
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j] = min(val[i][j-1] , val[ to[i][j-1] ][j-1]);
            }
    }

    for(int i = 1 ; i <= m ; i ++){
            //cout << u[i] << " " << v[i] << " " << e[i] << " , " << get_min_val(u[i] , v[i]) << endl;
            if(get_min_val(u[i] , v[i]) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , val[ node_for_edge[i] ][0] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 3e5 + 5;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int to[N] , p[N];
int  u[N] , v[N] , e[N];
int dep[N];

int segTreePos[N] , heavy[N] , chain[N];
int st[N << 2] , lazy[N << 2];

vii adj[N];

int dfs_hld(int u){

    if(u != 1)dep[u] = 1 + dep[p[u]];

    int sz = 1;
    int mx = 0;///heavy child
    for(ii A : adj[u]){
        int v  = A.second;
        int dx = A.first;///edge index

        if(v == p[u])continue;

         p[v]  = u;
        to[dx] = v;///map this edge to node v
        int curr = dfs_hld(v);

        if(curr > mx){
            mx = curr;
            heavy[u] = v;
        }

        sz += curr;
    }

    return sz;
}

void build_chains(){

    dfs_hld(1);

    int pos = 0;///pos in segment tree

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

        if(chain[ chainRoot ] == -1 || heavy[ p[ chainRoot ] ] != chainRoot){

            for(int j = chainRoot ; j != -1 ; j = heavy[j]){

                chain[j] = chainRoot;
                segTreePos[j] = ++ pos;

            }

        }

    }
}

void psh(int p , int l , int r){
    if(lazy[p] == 0)return;

    st[p] = max(st[p] , lazy[p]);

    if(l != r){
            lazy[p << 1]     = max(lazy[p << 1]     , lazy[p]);
            lazy[p << 1 | 1] = max(lazy[p << 1 | 1] , lazy[p]);
    }

    lazy[p] = 0;
}

void update_range(int p , int l , int r , int S , int E , int val){
    psh(p , l , r);

    if(l >= S && r <= E){
            lazy[p] = max(lazy[p] , val);
            psh(p , l , r);
            return;
    }
    if(l > E || r < S)return;

    int mid = (l + r) >> 1;

    update_range(p << 1 , l , mid , S , E , val);
    update_range(p << 1 | 1 , mid + 1 , r , S , E , val);

    st[p] = min(st[p << 1] , st[p << 1 | 1]);
}

int rmq(int p , int l , int r , int S , int E){
    psh(p , l , r);

    if(l >= S && r <= E)return st[p];
    if(l > E || r < S)  return 2e9;

    int mid = (l + r) >> 1;

    return min(rmq(p << 1 , l , mid , S , E) , rmq(p << 1 | 1 , mid + 1 , r , S , E));
}

int query(int u , int v){

    int ret = 2e9;
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            ret = min(ret , rmq(1 , 1 , N-1 , segTreePos[ chain[u] ] , segTreePos[u]));
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            ret = min(ret , rmq(1 , 1 , N-1 , l+1 , r));
    }

    return ret;
}

void update(int u , int v , int val){
    for( ; chain[u] != chain[v] ; u = p[chain[u]]){
            if(dep[ chain[u] ] < dep[ chain[v] ])swap(u , v);

            update_range(1 , 1 , N-1 , segTreePos[ chain[u] ] , segTreePos[u] , val);
    }

    if(u != v){
            int l = segTreePos[u] , r = segTreePos[v];
            if(l > r)swap(l , r);

            update_range(1 , 1 , N-1 , l+1 , r , val);
    }
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            assert(u <= n);
            assert(v <= n);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    build_chains();

    for(int i = 1 ; i <= n ; i ++){
            if(segTreePos[i] > n){
                cout << "i = " << i << " , pos = " << segTreePos[i] << endl;
                assert(5 > 6);
            }
    }

    for(int i = 1 ; i < n ; i ++){
            update_range(1 , 1 , N-1 , segTreePos[to[i]] , segTreePos[to[i]] , 1);
    }

    scanf("%d" , &m);
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update(u[i] , v[i] , e[i]);
    }

    for(int i = 1 ; i <= m ; i ++){
            int curr = query(u[i] , v[i]);

            if(curr != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            if(segTreePos[to[i]] > n){
                    cout << i << " " << to[i] << " " << segTreePos[to[i]] << endl;
                    assert(5 > 6);
            }
            int curr = rmq(1 , 1 , N-1 , segTreePos[to[i]] , segTreePos[to[i]]);
            if(curr == 2e9)curr = 1;
            printf("%d%c" , curr , i == n-1 ? '\n' : ' ');
    }

}

main(){

    memset(heavy , -1 , sizeof heavy);
    memset(p     , -1 , sizeof p    );

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5 , L = 20;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int u[N] , v[N] , e[N];
int to[N][L] , val[N][L];
int dep[N];

int node_for_edge[N];

vector < pair < int , int > > adj[N];

void dfs(int u , int p){
    to [u][0] = p;
    val[u][0] = 1;
    dep[u] = 1 + dep[p];

    for(pair < int , int > A : adj[u]){
            int v  = A.second;
            int edge_index = A.first;

            if(v == p)continue;

            node_for_edge[ edge_index ] = v;
            dfs(v , u);
    }
}

/// we try to find the LCA and we do updates on the way
void update_path(int u , int v , int new_val){
    if(u == v)return;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < L ; i ++){
            if(k & (1 << i)){
                    /// update
                    val[u][i] = max(val[u][i] , new_val);
                    u = to[u][i];
            }
    }

    if(u == v)return;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    /// update for u
                    val[u][i] = max(val[u][i] , new_val);
                    /// update for v
                    val[v][i] = max(val[v][i] , new_val);

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    /// update last 2 edges
    val[u][0] = max(val[u][0] , new_val);
    val[v][0] = max(val[v][0] , new_val);
}

int get_min_val(int u , int v){
    if(u == v)return 0;

    int ret = 2e9;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < k ; i ++){
            if(k & (1 << i)){
                    ret = min(ret , val[u][i]);
                    u = to[u][i];
            }
    }

    if(u == v)return ret;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    ret = min({ret , val[u][i] , val[v][i]});

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    return min({ ret , val[u][0] , val[v][0] });
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    dfs(1 , 0);

    /// build sparse table
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    to [i][j] =                   to [ to[i][j-1] ][j-1] ;
                    val[i][j] = max(val[i][j-1] , val[ to[i][j-1] ][j-1]);

                    //cout << val[i][j] << " ";
            }
    }
    //cout << endl;

    scanf("%d" , &m);

    /// take the queries and update values on paths
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update_path(u[i] , v[i] , e[i]);
    }

    /// after updates we push values from higher columns to lower columns
    for(int j = L-1 ; j >= 1 ; j --){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }

    for(int i = 1 ; i < L ; i ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }

        for(int j = L-1 ; j >= 1 ; j --){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }

    for(int i = 1 ; i < L ; i ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }

    /// after that all the values of the edges will be in val[i][0];

    /// then we initialize for minimum queries
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j] = min(val[i][j-1] , val[ to[i][j-1] ][j-1]);
            }
    }

    for(int i = 1 ; i <= m ; i ++){
            //cout << u[i] << " " << v[i] << " " << e[i] << " , " << get_min_val(u[i] , v[i]) << endl;
            if(get_min_val(u[i] , v[i]) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , val[ node_for_edge[i] ][0] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5 , L = 20;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int to[N][L];
int val[N][L];
int dep[N];
int node_of_edge[N];
int u[N] , v[N] , e[N];

vii adj[N];

void dfs(int u , int p){
    to[u][0] = p;
    dep[u] = 1 + dep[p];
    val[u][0] = 1;

    for(ii A : adj[u]){
            int v = A.second;
            int e = A.first;

            if(v == p)continue;

            node_of_edge[e] = v;
            dfs(v , u);
    }
}

int work(int u , int v , int new_val , bool mn){
    if(u == v)return 0;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    int ret = 2e9;
    for(int i = 0 ; i < L ; i ++){
            if(k & (1 << i)){
                    if(mn)ret = min(ret , val[u][i]);
                    else val[u][i] = max(val[u][i] , new_val);

                    u = to[u][i];
            }
    }

    if(u == v)return ret;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    if(mn)ret = min({ ret , val[u][i] , val[v][i] });
                    else {
                            val[u][i] = max(val[u][i] , new_val);
                            val[v][i] = max(val[v][i] , new_val);
                    }

                    u = to[u][i];
            }
    }

    if(mn)ret = min({ ret , val[u][0] , val[v][0] });
    else {
            val[u][0] = max(val[u][0] , new_val);
            val[v][0] = max(val[v][0] , new_val);
    }

    return ret;
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    dfs(1 , 0);

    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    to[i][j] = to[ to[i][j-1] ][j-1];
                    val[i][j] = min(val[i][j-1] , val[ to[i][j-1] ][j-1]);
            }
    }

    scanf("%d" , &m);

    for(int i = 0 ; i < m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            work(u[i] , v[i] , e[i] , 0);
    }

    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j] , val[i][j-1]);
            }
    }

    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[ to[i][j-1] ][j-1] = max(val[i][j] , val[ to[i][j-1] ][j-1]);
            }
    }

    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j] = min(val[i][j-1] , val[ to[i][j-1] ][j-1]);
            }
    }

    for(int i = 0 ; i < m ; i ++){
            if(work(u[i] , v[i] , e[i] , 1) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , val[ node_of_edge[i] ][0] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int w[N] , u[N] , v[N] , e[N] , p[N];
int edge[N];
vii adj[N];
int dep[N];

void dfs(int u , int pr){

    for(ii A : adj[u]){
            int v = A.second;
            int e = A.first;

            if(v != pr){
                    dep[v] = 1 + dep[u];
                    p[v] = u;
                    edge[v] = e;
                    dfs(v , u);
            }
    }
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
            w[i] = 1;
    }

    dfs(1 , 0);

    scanf("%d" , &m);

    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);

            int x = u[i] , y = v[i];

            while(x != y){
                    if(dep[x] < dep[y])swap(x , y);

                    w[ edge[x] ] = max(w[ edge[x] ] , e[i]);
                    x = p[x];
            }
    }

    for(int i = 1 ; i <= m ; i ++){
            int x = u[i] , y = v[i];

            int mn = 2e9;
            while(x != y){
                    if(dep[x] < dep[y])swap(x , y);

                    mn = min(mn , w[ edge[x] ]);
                    x = p[x];
            }

            if(mn != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , w[i] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 1e5 + 5;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int Euler = 0;
int E[N << 2 + 1];
int L[N << 2 + 1];
int H[N]; /// first occurrence

int st  [N << 8];
int mn  [N << 8];
int mx  [N << 8];
int lazy[N << 8];
int dep[N];

int u[N] , v[N] , e[N];
int ans[N << 2 + 1];

vii adj[N];
int node_for_edge[N];

int mrg(int a , int b){
    if(a == 1e9)return b;
    if(b == 1e9)return a;

    if(dep[a] < dep[b]) return a;
    return b;
}

void build(int p , int l , int r){
    if(l == r){
            st[p] = E[l];
            return;
    }

    int mid = (l + r) >> 1;

    build(p << 1 , l , mid);
    build(p << 1 | 1 , mid + 1 , r);

    st[p] = mrg(st[p << 1] , st[p << 1 | 1]);
}

int query_lca(int p , int l , int r , int S , int E){
    if(l >= S && r <= E) return st[p];
    if(l > E || r < S) return 1e9;

    int mid = (l + r ) >> 1;

    return mrg(query_lca(p << 1 , l , mid , S , E) , query_lca(p << 1 | 1 , mid + 1 , r , S , E));
}

void psh(int p , int l , int r){
    if(lazy[p] == 0)return;

    mx[p] = max(mx[p] , lazy[p]);

    if(l != r){
            lazy[p << 1] = max(lazy[p << 1] , lazy[p]);
            lazy[p << 1 | 1] = max(lazy[p << 1 | 1] , lazy[p]);
    }

    lazy[p] = 0;
}

void update(int p , int l , int r , int S , int E , int new_val){
    psh(p , l , r);

    if(l >= S && r <= E){
            lazy[p] = max(lazy[p] , new_val);
            psh(p , l , r);
            return;
    }
    if(l > E || r < S)return;

    int mid = (l + r) >> 1;

    update(p << 1     , l       , mid , S , E , new_val);
    update(p << 1 | 1 , mid + 1 , r   , S , E , new_val);

    mx[p] = max(mx[p << 1] , mx[p << 1 | 1]);
}

int query_max(int p , int l , int r , int S , int E){
    psh(p , l , r);

    if(l >= S && r <= E)return mx[p];
    if(l > E || r < S)return 0;

    int mid = (l + r) >> 1;

    return max(query_max(p << 1 , l , mid , S , E) , query_max(p << 1 | 1 , mid + 1 , r , S , E));
}

void build_min(int p , int l , int r){
    if(l == r){
            mn[p] = ans[l];
            return;
    }

    int mid = (l + r) >> 1;

    build_min(p << 1 , l , mid);
    build_min(p << 1 | 1 , mid + 1 , r);

    mn[p] = min(mn[p << 1] , mn[p << 1 | 1]);
}

int query_min(int p , int l , int r , int S , int E){
    if(l >= S && r <= E)return mn[p];
    if(l > E || r < S)return 2e9;

    int mid = (l + r) >> 1;

    return min(query_min(p << 1 , l , mid , S , E) , query_min(p << 1 | 1 , mid + 1 , r , S , E));
}

int get_lca(int u , int v){
    int l = H[u] , r = H[v];

    if(l > r)swap(l , r);

    return query_lca(1 , 1 , 2*n - 1 , l , r);
}

void update_path(int u , int lca , int w){
    if(H[u] < H[lca]){
            update(1 , 1 , 2*n - 1 , H[u] , H[lca] - 1 , w);
    }
    else {
            update(1 , 1 , 2*n - 1 , H[lca] + 1 , H[u] , w);
    }
}

void change(int u , int v , int w){
    int lca = get_lca(u , v);

    if(u != lca)update_path(u , lca , w);
    if(v != lca)update_path(v , lca , w);
}

int ask(int u , int lca){

    //cout << "u = " << u << " , lca = " << lca << endl;
    //cout << H[u] << " " << H[lca] << endl;
    if(H[u] < H[lca]){
            return query_min(1 , 1 , 2*n - 1 , H[u] , H[lca] - 1);
    }
    else {
            return query_min(1 , 1 , 2*n - 1 , H[lca] + 1 , H[u]);
    }
}

int get_min(int u , int v){
    int lca = get_lca(u , v);

    int ret = 2e9;
    if(u != lca)ret = min(ret , ask(u , lca));
    if(v != lca)ret = min(ret , ask(v , lca));

    return ret;
}

void dfs(int u , int p){

    dep[u] = 1 + dep[p];

    Euler ++;
    H[u] = Euler;
    E[Euler] = u;
    L[Euler] = dep[u];

    for(ii A : adj[u]){
            int v = A.second;
            int e = A.first;

            if(v == p)continue;

            node_for_edge[e] = v;
            dfs(v , u);

            Euler ++;
            E[Euler] = u;
            L[Euler] = dep[u];
    }
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    dfs(1 , 0);

    int sz = 2 * n - 1;

    build(1 , 1 , sz);

    scanf("%d" , &m);

    for(int i = 1 ; i <= 2*n - 1 ; i ++){
            update(1 , 1 , 2*n - 1 , i , i , 1);
    }
    for(int i = 0 ; i < m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);

            change(u[i] , v[i] , e[i]);
    }

    //cout << endl;
    for(int i = 1 ; i <= 2*n - 1 ; i ++){
            ans[i] = query_max(1 , 1 , 2*n - 1 , i , i);
            //cout << ans[i] << " ";
    }
    //cout << endl;

    build_min(1 , 1 , 2*n - 1);

    /*
    cout << endl;
    for(int i = 1 ; i <= 2*n-1 ; i ++){
            cout << query_min(1 , 1 , 2*n - 1 , i , i) << " ";
    }
    cout << endl;
    */

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

            //cout << "query: " << u[i] << " " << v[i] << " " << e[i] << endl;
            //cout << "ans: " << get_min(u[i] , v[i]) << endl;
            if(get_min(u[i] , v[i]) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            int u = node_for_edge[i];

            printf("%d%c" , ans[H[u]] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include<bits/stdc++.h>

using namespace std;

using ll   = long long;
using ii   = pair   < int , int >;
using i3   = pair   < int , ii  >;
using li   = pair   < ll  , int >;
using lii  = pair   < ll  , ii  >;
using pll  = pair   < ll  , ll  >;
using vi   = vector < int       >;
using vl   = vector < ll        >;
using vii  = vector < ii        >;
using vli  = vector < li        >;
using vpll = vector < pll       >;
using vi3  = vector < i3        >;
using vlii = vector < lii       >;

const int N = 2e5 + 5 , L = 20;
const ll INF = 1e17 + 7;
const double eps = 1e-9 , PI = acos(-1);

int n , m;

int u[N] , v[N] , e[N];
int to[N][L] , val[N][L];
int dep[N];

int node_for_edge[N];

vector < pair < int , int > > adj[N];

void dfs(int u , int p){
    to [u][0] = p;
    val[u][0] = 1;
    dep[u] = 1 + dep[p];

    for(pair < int , int > A : adj[u]){
            int v  = A.second;
            int edge_index = A.first;

            if(v == p)continue;

            node_for_edge[ edge_index ] = v;
            dfs(v , u);
    }
}

/// we try to find the LCA and we do updates on the way
void update_path(int u , int v , int new_val){
    if(u == v)return;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < L ; i ++){
            if(k & (1 << i)){
                    /// update
                    val[u][i] = max(val[u][i] , new_val);
                    u = to[u][i];
            }
    }

    if(u == v)return;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    /// update for u
                    val[u][i] = max(val[u][i] , new_val);
                    /// update for v
                    val[v][i] = max(val[v][i] , new_val);

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    /// update last 2 edges
    val[u][0] = max(val[u][0] , new_val);
    val[v][0] = max(val[v][0] , new_val);
}

int get_min_val(int u , int v){
    if(u == v)return 0;

    int ret = 2e9;

    if(dep[u] < dep[v])swap(u , v);

    int k = dep[u] - dep[v];

    for(int i = 0 ; i < k ; i ++){
            if(k & (1 << i)){
                    ret = min(ret , val[u][i]);
                    u = to[u][i];
            }
    }

    if(u == v)return ret;

    for(int i = L-1 ; i >= 0 ; i --){
            if(to[u][i] != to[v][i]){
                    ret = min({ret , val[u][i] , val[v][i]});

                    u = to[u][i];
                    v = to[v][i];
            }
    }

    return min({ ret , val[u][0] , val[v][0] });
}

void solve(int testCase){

    scanf("%d" , &n);

    for(int i = 1 ; i < n ; i ++){
            int u , v; scanf("%d %d" , &u , &v);

            adj[u].push_back({i , v});
            adj[v].push_back({i , u});
    }

    dfs(1 , 0);

    /// build sparse table
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    to [i][j] =                   to [ to[i][j-1] ][j-1] ;
                    val[i][j] = max(val[i][j-1] , val[ to[i][j-1] ][j-1]);

                    //cout << val[i][j] << " ";
            }
    }
    //cout << endl;

    scanf("%d" , &m);

    /// take the queries and update values on paths
    for(int i = 1 ; i <= m ; i ++){
            scanf("%d %d %d" , &u[i] , &v[i] , &e[i]);
            update_path(u[i] , v[i] , e[i]);
    }

    /// after updates we push values from higher columns to lower columns
    for(int i = 1 ; i <= n ; i ++){
            for(int j = L-1 ; j >= 1 ; j --){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }

    /*
    for(int j = L-1 ; j >= 1 ; j --){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j-1] = max(val[i][j-1] , val[i][j]);
                    val[ to[i][j-1] ][j-1] = max(val[ to[i][j-1] ][j-1] , val[i][j]);
            }
    }
    */
    /// after that all the values of the edges will be in val[i][0];

    /// then we initialize for minimum queries
    for(int j = 1 ; j < L ; j ++){
            for(int i = 1 ; i <= n ; i ++){
                    val[i][j] = min(val[i][j-1] , val[ to[i][j-1] ][j-1]);
            }
    }

    for(int i = 1 ; i <= m ; i ++){
            //cout << u[i] << " " << v[i] << " " << e[i] << " , " << get_min_val(u[i] , v[i]) << endl;
            if(get_min_val(u[i] , v[i]) != e[i]){
                    printf("-1\n");
                    return;
            }
    }

    for(int i = 1 ; i < n ; i ++){
            printf("%d%c" , val[ node_for_edge[i] ][0] , i == n-1 ? '\n' : ' ');
    }

}

main(){

    int t = 1;
    // scanf("%d" , &t);

    for(int testCase = 1 ; testCase <= t ; testCase ++){
            solve(testCase);
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long

typedef long long ll;
typedef pair<int, int> pii;

vector<vector<int>> way;
vector<int> deep, tin, tout;
vector<int> pre;
map<pii, int> mapi;
vector<vector<int>> spar;

int t = 0;

void dfs(int v, int p, int d) {
    spar[0][v] = p;
    deep[v] = d;
    tin[v] = t;
    pre[v] = p;
    t++;
    for (int u : way[v]) {
        if (u != p) {
            dfs(u, v, d + 1);
        }
    }
    tout[v] = t;
}

struct pas{
    int in;
    int to;
    int b;
};

bool operator<(pas a, pas b) {
    if (a.b == b.b) {
        return a.in < b.in;
    }
    return  a.b < b.b;
}

bool check(int v, int u) {
    return tin[v] < tin[u] && tout[v] > tout[u];
}

void change(int v, int u, int b) {
    while (v != u) {
        int x = pre[v];
        mapi[{x, v}] = b;
        mapi[{v, x}] = b;
        v = x;
    }
}

void paint(pas a) {
    int v = a.in, u = a.to;
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    change(a.in, v, a.b);
    change(a.to, v, a.b);
}

int find_mini(int v, int u) {
    int ans = 1e6;
    while (v != u) {
        int x = pre[v];
        ans = min(ans, mapi[{v, x}]);
        v = x;
    }
    return ans;
}

bool proof(pas a) {
    int v = a.in, u = a.to;
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    return min(find_mini(a.in, v), find_mini(a.to, v)) == a.b;
}

int main() {
    int n;
    cin >> n;
    way.resize(n);
    vector<pii> byp(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        way[a].push_back(b);
        way[b].push_back(a);
        byp[i] = {a, b};
        mapi[{a, b}] = 1e6;
        mapi[{b, a}] = 1e6;
    }
    spar.resize(20, vector<int>(n));

    int m;
    cin >> m;
    vector<pas> beauty(m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        beauty[i] = {a - 1, b - 1, c};
    }
    sort(beauty.begin(), beauty.end());
    deep.resize(n);
    pre.resize(n);
    tin.resize(n);
    tout.resize(n);

    dfs(0, -1, 1);
    spar[0][0] = 0;

    for (int i = 1; i < 15; i++) {
        for (int j = 0; j < n; j++) {
            spar[i][j] = spar[i - 1][spar[i - 1][j]];
        }
    }

    for (int i = 0; i < m; i++) {
        paint(beauty[i]);
        /*
        for (int i = 0; i < n - 1; i++) {
            cout << mapi[byp[i]] << " ";
        }
        cout << "\n";
        */
    }
    for (int i = 0; i < m; i++) {
        if (!proof(beauty[i])) {
            cout << -1;
            return 0;
        }
    }
    for (int i = 0; i < n - 1; i++) {
        cout << mapi[byp[i]] << " ";
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("fast-math")

typedef long long ll;
typedef pair<int, int> pii;

vector<vector<int>> way;
vector<int> deep, tin, tout;
vector<int> pre;
vector<vector<int>> spar;

vector<int> cost, reb;
vector<pii> byp;

int t = 0;
int n;

void dfs(int v, int p, int d) {
    if (p != -1) {
        for (int i = 0; i < n; i++) {
            if (byp[i] == make_pair(v, p) || byp[i] == make_pair(p, v)) {
                reb[v] = i;
            }
        }
    }
    spar[0][v] = p;
    deep[v] = d;
    tin[v] = t;
    pre[v] = p;
    t++;
    for (int u : way[v]) {
        if (u != p) {
            dfs(u, v, d + 1);
        }
    }
    t++;
    tout[v] = t;
}

struct pas{
    int in;
    int to;
    int b;
};

bool operator<(pas a, pas b) {
    if (a.b == b.b) {
        return a.in < b.in;
    }
    return  a.b < b.b;
}

bool check(int v, int u) {
    return tin[v] <= tin[u] && tout[v] >= tout[u];
}

void change(int v, int u, int b) {
    while (v != u) {
        int x = pre[v];
        cost[reb[v]] = b;
        v = x;
    }
}

void paint(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    change(a.in, v, a.b);
    change(a.to, v, a.b);
}

int find_mini(int v, int u) {
    int ans = 1e6;
    while (v != u) {
        int x = pre[v];
        ans = min(ans, cost[reb[v]]);
        v = x;
    }
    return ans;
}

bool proof(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    return min(find_mini(a.in, v), find_mini(a.to, v)) == a.b;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    cin >> n;
    way.resize(n);
    byp.resize(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        way[a].push_back(b);
        way[b].push_back(a);
        byp[i] = {a, b};
    }
    spar.resize(20, vector<int>(n));

    int m;
    cin >> m;
    vector<pas> beauty(m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        beauty[i] = {a - 1, b - 1, c};
    }
    sort(beauty.begin(), beauty.end());
    deep.resize(n);
    pre.resize(n);
    tin.resize(n);
    tout.resize(n);
    cost.resize(n, 1e6);
    reb.resize(n);

    dfs(0, -1, 1);
    spar[0][0] = 0;

    for (int i = 1; i < 15; i++) {
        for (int j = 0; j < n; j++) {
            spar[i][j] = spar[i - 1][spar[i - 1][j]];
        }
    }

    for (int i = 0; i < m; i++) {
        paint(beauty[i]);
    }
    for (int i = 0; i < m; i++) {
        if (!proof(beauty[i])) {
            cout << -1;
            return 0;
        }
    }
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n; j++) {
            if (byp[i] == make_pair(j, pre[j]) || byp[i] == make_pair(pre[j], j)) {
                cout << cost[reb[j]] << " ";
            }
        }
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long

typedef long long ll;
typedef pair<int, int> pii;

vector<vector<int>> way;
vector<int> deep, tin, tout;
vector<int> pre;
map<pii, int> mapi;
vector<vector<int>> spar;

int t = 0;

void dfs(int v, int p, int d) {
    spar[0][v] = p;
    deep[v] = d;
    tin[v] = t;
    pre[v] = p;
    t++;
    for (int u : way[v]) {
        if (u != p) {
            dfs(u, v, d + 1);
        }
    }
    t++;
    tout[v] = t;
}

struct pas{
    int in;
    int to;
    int b;
};

bool operator<(pas a, pas b) {
    if (a.b == b.b) {
        return a.in < b.in;
    }
    return  a.b < b.b;
}

bool check(int v, int u) {
    return tin[v] <= tin[u] && tout[v] >= tout[u];
}

void change(int v, int u, int b) {
    while (v != u) {
        int x = pre[v];
        mapi[{x, v}] = b;
        mapi[{v, x}] = b;
        v = x;
    }
}

void paint(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    change(a.in, v, a.b);
    change(a.to, v, a.b);
}

int find_mini(int v, int u) {
    int ans = 1e6;
    while (v != u) {
        int x = pre[v];
        ans = min(ans, mapi[{v, x}]);
        v = x;
    }
    return ans;
}

bool proof(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    return min(find_mini(a.in, v), find_mini(a.to, v)) == a.b;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    way.resize(n);
    vector<pii> byp(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        way[a].push_back(b);
        way[b].push_back(a);
        byp[i] = {a, b};
        mapi[{a, b}] = 1e6;
        mapi[{b, a}] = 1e6;
    }
    spar.resize(20, vector<int>(n));

    int m;
    cin >> m;
    vector<pas> beauty(m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        beauty[i] = {a - 1, b - 1, c};
    }
    sort(beauty.begin(), beauty.end());
    deep.resize(n);
    pre.resize(n);
    tin.resize(n);
    tout.resize(n);

    dfs(0, -1, 1);
    spar[0][0] = 0;

    for (int i = 1; i < 15; i++) {
        for (int j = 0; j < n; j++) {
            spar[i][j] = spar[i - 1][spar[i - 1][j]];
        }
    }

    for (int i = 0; i < m; i++) {
        paint(beauty[i]);
    }
    for (int i = 0; i < m; i++) {
        if (!proof(beauty[i])) {
            cout << -1;
            return 0;
        }
    }
    for (int i = 0; i < n - 1; i++) {
        cout << mapi[byp[i]] << " ";
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long

typedef long long ll;
typedef pair<int, int> pii;

vector<vector<int>> way;
vector<int> deep, tin, tout;
vector<int> pre;
map<pii, int> mapi;
vector<vector<int>> spar;

int t = 0;

void dfs(int v, int p, int d) {
    spar[0][v] = p;
    deep[v] = d;
    tin[v] = t;
    pre[v] = p;
    t++;
    for (int u : way[v]) {
        if (u != p) {
            dfs(u, v, d + 1);
        }
    }
    t++;
    tout[v] = t;
}

struct pas{
    int in;
    int to;
    int b;
};

bool operator<(pas a, pas b) {
    if (a.b == b.b) {
        return a.in < b.in;
    }
    return  a.b < b.b;
}

bool check(int v, int u) {
    return tin[v] <= tin[u] && tout[v] >= tout[u];
}

void change(int v, int u, int b) {
    while (v != u) {
        int x = pre[v];
        mapi[{x, v}] = b;
        mapi[{v, x}] = b;
        v = x;
    }
}

void paint(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    change(a.in, v, a.b);
    change(a.to, v, a.b);
}

int find_mini(int v, int u) {
    int ans = 1e6;
    while (v != u) {
        int x = pre[v];
        ans = min(ans, mapi[{v, x}]);
        v = x;
    }
    return ans;
}

bool proof(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    return min(find_mini(a.in, v), find_mini(a.to, v)) == a.b;
}

int main() {
    int n;
    cin >> n;
    way.resize(n);
    vector<pii> byp(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        way[a].push_back(b);
        way[b].push_back(a);
        byp[i] = {a, b};
        mapi[{a, b}] = 1e6;
        mapi[{b, a}] = 1e6;
    }
    spar.resize(20, vector<int>(n));

    int m;
    cin >> m;
    vector<pas> beauty(m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        beauty[i] = {a - 1, b - 1, c};
    }
    sort(beauty.begin(), beauty.end());
    deep.resize(n);
    pre.resize(n);
    tin.resize(n);
    tout.resize(n);

    dfs(0, -1, 1);
    spar[0][0] = 0;

    for (int i = 1; i < 15; i++) {
        for (int j = 0; j < n; j++) {
            spar[i][j] = spar[i - 1][spar[i - 1][j]];
        }
    }

    for (int i = 0; i < m; i++) {
        paint(beauty[i]);
        /*
        for (int i = 0; i < n - 1; i++) {
            cout << mapi[byp[i]] << " ";
        }
        cout << "\n";
        */
    }
    for (int i = 0; i < m; i++) {
        if (!proof(beauty[i])) {
            cout << -1;
            return 0;
        }
    }
    for (int i = 0; i < n - 1; i++) {
        cout << mapi[byp[i]] << " ";
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long

#pragma GCC optimize("Ofast,no-stack-protector")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,avx2,tune=native")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("fast-math")

typedef long long ll;
typedef pair<int, int> pii;

vector<vector<int>> way;
vector<int> deep, tin, tout;
vector<int> pre;
map<pii, int> mapi;
vector<vector<int>> spar;

int t = 0;

void dfs(int v, int p, int d) {
    spar[0][v] = p;
    deep[v] = d;
    tin[v] = t;
    pre[v] = p;
    t++;
    for (int u : way[v]) {
        if (u != p) {
            dfs(u, v, d + 1);
        }
    }
    t++;
    tout[v] = t;
}

struct pas{
    int in;
    int to;
    int b;
};

bool operator<(pas a, pas b) {
    if (a.b == b.b) {
        return a.in < b.in;
    }
    return  a.b < b.b;
}

bool check(int v, int u) {
    return tin[v] <= tin[u] && tout[v] >= tout[u];
}

void change(int v, int u, int b) {
    while (v != u) {
        int x = pre[v];
        mapi[{x, v}] = b;
        mapi[{v, x}] = b;
        v = x;
    }
}

void paint(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    change(a.in, v, a.b);
    change(a.to, v, a.b);
}

int find_mini(int v, int u) {
    int ans = 1e6;
    while (v != u) {
        int x = pre[v];
        ans = min(ans, mapi[{v, x}]);
        v = x;
    }
    return ans;
}

bool proof(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    return min(find_mini(a.in, v), find_mini(a.to, v)) == a.b;
}

int main() {
    ios_base::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    int n;
    cin >> n;
    way.resize(n);
    vector<pii> byp(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        way[a].push_back(b);
        way[b].push_back(a);
        byp[i] = {a, b};
        mapi[{a, b}] = 1e6;
        mapi[{b, a}] = 1e6;
    }
    spar.resize(20, vector<int>(n));

    int m;
    cin >> m;
    vector<pas> beauty(m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        beauty[i] = {a - 1, b - 1, c};
    }
    sort(beauty.begin(), beauty.end());
    deep.resize(n);
    pre.resize(n);
    tin.resize(n);
    tout.resize(n);

    dfs(0, -1, 1);
    spar[0][0] = 0;

    for (int i = 1; i < 15; i++) {
        for (int j = 0; j < n; j++) {
            spar[i][j] = spar[i - 1][spar[i - 1][j]];
        }
    }

    for (int i = 0; i < m; i++) {
        paint(beauty[i]);
    }
    for (int i = 0; i < m; i++) {
        if (!proof(beauty[i])) {
            cout << -1;
            return 0;
        }
    }
    for (int i = 0; i < n - 1; i++) {
        cout << mapi[byp[i]] << " ";
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

//#define int long long

typedef long long ll;
typedef pair<int, int> pii;

vector<vector<int>> way;
vector<int> deep, tin, tout;
vector<int> pre;
map<pii, int> mapi;
vector<vector<int>> spar;

int t = 0;

void dfs(int v, int p, int d) {
    spar[0][v] = p;
    deep[v] = d;
    tin[v] = t;
    pre[v] = p;
    t++;
    for (int u : way[v]) {
        if (u != p) {
            dfs(u, v, d + 1);
        }
    }
    t++;
    tout[v] = t;
}

struct pas{
    int in;
    int to;
    int b;
};

bool operator<(pas a, pas b) {
    if (a.b == b.b) {
        return a.in < b.in;
    }
    return  a.b < b.b;
}

bool check(int v, int u) {
    return tin[v] <= tin[u] && tout[v] >= tout[u];
}

void change(int v, int u, int b) {
    while (v != u) {
        int x = pre[v];
        mapi[{x, v}] = b;
        mapi[{v, x}] = b;
        v = x;
    }
}

void paint(pas a) {
    int v = a.in, u = a.to;
    if (deep[v] < deep[u]) {
        swap(u, v);
    }
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    change(a.in, v, a.b);
    change(a.to, v, a.b);
}

int find_mini(int v, int u) {
    int ans = 1e6;
    while (v != u) {
        int x = pre[v];
        ans = min(ans, mapi[{v, x}]);
        v = x;
    }
    return ans;
}

bool proof(pas a) {
    int v = a.in, u = a.to;
    for (int i = 14; i >= 0; i--) {
        int x = spar[i][v];
        if (!check(x, u)) {
            v = x;
        }
    }
    v = spar[0][v];
    return min(find_mini(a.in, v), find_mini(a.to, v)) == a.b;
}

int main() {
    int n;
    cin >> n;
    way.resize(n);
    vector<pii> byp(n);
    for (int i = 0; i < n - 1; i++) {
        int a, b;
        cin >> a >> b;
        a--;
        b--;
        way[a].push_back(b);
        way[b].push_back(a);
        byp[i] = {a, b};
        mapi[{a, b}] = 1e6;
        mapi[{b, a}] = 1e6;
    }
    spar.resize(20, vector<int>(n));

    int m;
    cin >> m;
    vector<pas> beauty(m);
    for (int i = 0; i < m; i++) {
        int a, b, c;
        cin >> a >> b >> c;
        beauty[i] = {a - 1, b - 1, c};
    }
    sort(beauty.begin(), beauty.end());
    deep.resize(n);
    pre.resize(n);
    tin.resize(n);
    tout.resize(n);

    dfs(0, -1, 1);
    spar[0][0] = 0;

    for (int i = 1; i < 15; i++) {
        for (int j = 0; j < n; j++) {
            spar[i][j] = spar[i - 1][spar[i - 1][j]];
        }
    }

    for (int i = 0; i < m; i++) {
        paint(beauty[i]);
        /*
        for (int i = 0; i < n - 1; i++) {
            cout << mapi[byp[i]] << " ";
        }
        cout << "\n";
        */
    }
    for (int i = 0; i < m; i++) {
        if (!proof(beauty[i])) {
            cout << -1;
            return 0;
        }
    }
    for (int i = 0; i < n - 1; i++) {
        cout << mapi[byp[i]] << " ";
    }

    return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

const int MAX = 5e3+10;

vector<vector<int> > g(MAX);
int in[MAX], h[MAX], sz[MAX];
int pai[MAX], t;

void build(int k, int p = -1, int f = 1) {
	in[k] = t++; sz[k] = 1;
	for (int& i : g[k]) if (i != p) {
		pai[i] = k;
		h[i] = (i == g[k][0] ? h[k] : i);
		build(i, k, f); sz[k] += sz[i];

		if (sz[i] > sz[g[k][0]]) swap(i, g[k][0]);
	}
	if (p*f == -1) t = 0, h[k] = k, build(k, -1, 0);
}

int lca(int a, int b) {
	if (in[a] < in[b]) swap(a, b);
	return h[a] == h[b] ? b : lca(pai[h[a]], b);
}

int val[MAX], val2[MAX], ans[MAX];

int dfs(int k, int p=-1) {
	val2[k] = val[k];
	for (int i : g[k]) if (i != p) val2[k] += dfs(i, k);
	return val2[k];
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i <= n; i++) ans[i] = 1;
	map<pair<int, int>, int> mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
		g[a].pb(b);
		g[b].pb(a);
	}
	build(0);
	pai[0] = 0;
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, m; cin >> a >> b >> m;
		a--, b--;
		qu.pb({{a, b}, m});
	}
	sort(qu.begin(), qu.end(), [](pair<ii, int> a, pair<ii, int> b){ return a.s < b.s; });
	for (int i = 0; i < q; i++) {
		//cout << "---- " << i << endl;
		memset(val, 0, sizeof(val));
		memset(val2, 0, sizeof(val2));
		for (int j = i+1; j < q; j++) if (qu[j].s > qu[i].s) {
			int a, b;
			tie(a, b) = qu[j].f;
			//cout << "colocando no " << a << " " << b << endl;
			val[a]++;
			val[b]++;
			int l = lca(a, b);
			val[l]--;
			if (l != a and l != b and pai[l] != l) val[pai[l]]--;
		}
		dfs(0);
		int a, b;
		tie(a, b) = qu[i].f;
		int l = lca(a, b);
		bool deu = 0;
		while (a != l) {
			if (!val2[a]) {
				ans[a] = qu[i].s;
				deu = 1;
			}
			a = pai[a];
		}
		while (b != l) {
			if (!val2[b]) {
				ans[b] = qu[i].s;
				deu = 1;
			}
			b = pai[b];
		}
		if (!deu) return cout << -1 << endl, 0;
	}
	vector<int> anss(n-1, 1);
	for (int i = 0; i < n; i++) if (pai[i] != i) {
		int x = ans[i];
		anss[mm[make_pair(i, pai[i])]] = x;
	}
	for (int i = 0; i < n-1; i++) cout << anss[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

const int MAX = 5e3+10;

namespace dinic {
	struct edge {
		unsigned short to, rev;
		edge(short to_, char cap_, short rev_) : to(to_), rev(rev_) {
			if (cap_) to |= (1<<15);
		}
	};

	vector<edge> g[2*MAX];
	vector<int> lev;
	int n;

	void build(int n_) {
		n = n_;
	}

	void add(int a, int b) { // de a pra b com cap. c
		g[a].pb(edge(b, 1, g[b].size()));
		g[b].pb(edge(a, 0, g[a].size()-1));
	}
	bool bfs(int s, int t) {
		lev = vector<int>(n, -1); lev[s] = 0;
		queue<int> q; q.push(s);
		while (q.size()) {
			int u = q.front(); q.pop();
			for (auto& i : g[u]) {
				if (lev[i.to&32767] != -1 or !(i.to>>15)) continue;
				lev[i.to&32767] = lev[u] + 1;
				if ((i.to&32767) == t) return 1;
				q.push(i.to&32767);
			}
		}
		return 0;
	}
	int dfs(int v, int s, int f = INF){
		if (v == s) return f;
		int tem = f;
		for (auto& i : g[v]) {
			if (lev[i.to&32767] != lev[v] + 1 or !(i.to>>15)) continue;
			int foi = dfs(i.to&32767, s, min(tem, i.to>>15));
			if (foi) {
				tem -= foi;
				i.to ^= (1<<15);
				g[i.to&32767][i.rev].to ^= (1<<15);
			}
		}
		if (f == tem) lev[v] = -1;
		return f - tem;
	}
	int max_flow(int s, int t) {
		int f = 0;
		while (bfs(s, t)) f += dfs(s, t);
		return f;
	}
}

int val[MAX], lev[MAX], pai[MAX], ans[MAX];
vector<int> g[MAX];

void dfs(int k=0, int p=0, int d=0) {
	pai[k] = p;
	lev[k] = d;
	for (int i : g[k]) if (i != p) dfs(i, k, d+1);
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i < n-1; i++) val[i] = 1;
	map<pair<int, int>, int > mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		g[a].pb(b);
		g[b].pb(a);
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
	}
	dfs();
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		qu.pb({{a, b}, c});
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int& x = val[mm[make_pair(a, pai[a])]];
			x = max(x, c);
			a = pai[a];
		}
	}
//	for (int i = 0; i < n-1; i++) cout << val[i] << " ";
//	cout << endl;
	dinic::build(n-1+q+2);
	for (int i = 0; i < n-1; i++) dinic::add(n-1+q, i);
	for (int i = 0; i < q; i++) dinic::add(n-1+i, n+q);
	for (int i = 0; i < q; i++) {
		int a = qu[i].f.f, b = qu[i].f.s;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int ind = mm[make_pair(a, pai[a])];
			if (val[ind] <= qu[i].s) dinic::add(ind, n-1+i);
			a = pai[a];
		}
	}
	dinic::max_flow(n-1+q, n+q);
	for (int i = 0; i < n-1; i++) {
		ans[i] = 1e6;
		for (auto e : dinic::g[i]) if ((e.to&32767) != n-1+q and !(e.to>>15))
			ans[i] = qu[e.to-(n-1)].s;
	}
//	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
//	cout << endl;
	for (auto i : qu) {
		int a = i.f.f, b = i.f.s;
		int mi = INF;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			mi = min(mi, ans[mm[make_pair(a, pai[a])]]);
			a = pai[a];
		}
		if (mi != i.s) return cout << -1 << endl, 0;
	}
	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

struct dinic {
	struct edge {
		int to, cap, rev, flow; // para, capacidade, id da reversa, fluxo
		bool res; // se a aresta eh residual
		edge(int to_, int cap_, int rev_, bool res_)
			: to(to_), cap(cap_), rev(rev_), flow(0), res(res_) {}
	};

	vector<vector<edge>> g;
	vector<int> lev;
	dinic(int n): g(n){}

	void add(int a, int b, int c) { // de a pra b com cap. c
		g[a].pb(edge(b, c, g[b].size(), false));
		g[b].pb(edge(a, 0, g[a].size()-1, true));
	}
	bool bfs(int s, int t) {
		lev = vector<int>(g.size(), -1); lev[s] = 0;
		queue<int> q; q.push(s);
		while (q.size()) {
			int u = q.front(); q.pop();
			for (auto& i : g[u]) {
				if (lev[i.to] != -1 or (i.flow == i.cap)) continue;
				lev[i.to] = lev[u] + 1;
				if (i.to == t) return 1;
				q.push(i.to);
			}
		}
		return 0;
	}
	int dfs(int v, int s, int f = INF){
		if (v == s) return f;
		int tem = f;
		for (auto& i : g[v]) {
			if (lev[i.to] != lev[v] + 1 or (i.flow == i.cap)) continue;
			int foi = dfs(i.to, s, min(tem, i.cap - i.flow));
			tem -= foi, i.flow += foi, g[i.to][i.rev].flow -= foi;
		}
		if (f == tem) lev[v] = -1;
		return f - tem;
	}
	int max_flow(int s, int t) {
		int f = 0;
		while (bfs(s, t)) f += dfs(s, t);
		return f;
	}
	vector<pair<int, int> > get_cut(int s, int t) {
		max_flow(s, t);
		vector<pair<int, int> > cut;
		vector<int> vis(g.size(), 0), st = {s};
		vis[s] = 1;
		while (st.size()) {
			int u = st.back(); st.pop_back();
			for (auto e : g[u]) if (!vis[e.to] and e.flow < e.cap) {
				vis[e.to] = 1;
				st.push_back(e.to);
			}
		}
		for (int i = 0; i < g.size(); i++) for (auto e : g[i])
			if (vis[i] and !vis[e.to] and !e.res) cut.push_back({i, e.to});
		return cut;
	}
};

const int MAX = 5e3+10;

int val[MAX], lev[MAX], pai[MAX], ans[MAX];
vector<int> g[MAX];

void dfs(int k=0, int p=0, int d=0) {
	pai[k] = p;
	lev[k] = d;
	for (int i : g[k]) if (i != p) dfs(i, k, d+1);
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i < n-1; i++) val[i] = 1;
	map<pair<int, int>, int > mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		g[a].pb(b);
		g[b].pb(a);
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
	}
	dfs();
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		qu.pb({{a, b}, c});
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int& x = val[mm[make_pair(a, pai[a])]];
			x = max(x, c);
			a = pai[a];
		}
	}
//	for (int i = 0; i < n-1; i++) cout << val[i] << " ";
//	cout << endl;
	dinic d(n-1+q+2);
	for (int i = 0; i < n-1; i++) d.add(n-1+q, i, 1);
	for (int i = 0; i < q; i++) d.add(n-1+i, n+q, 1);
	for (int i = 0; i < q; i++) {
		int a = qu[i].f.f, b = qu[i].f.s;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int ind = mm[make_pair(a, pai[a])];
			if (val[ind] <= qu[i].s) d.add(ind, n-1+i, 1);
			a = pai[a];
		}
	}
	d.max_flow(n-1+q, n+q);
	for (int i = 0; i < n-1; i++) {
		ans[i] = 1e6;
		for (auto e : d.g[i]) if (!e.res and e.flow) ans[i] = qu[e.to-(n-1)].s;
	}
//	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
//	cout << endl;
	for (auto i : qu) {
		int a = i.f.f, b = i.f.s;
		int mi = INF;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			mi = min(mi, ans[mm[make_pair(a, pai[a])]]);
			a = pai[a];
		}
		if (mi != i.s) return cout << -1 << endl, 0;
	}
	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

const int MAX = 1e5+10;

namespace lct {
	struct node {
		int p, path_p, ch[2];
		ll val, sub;
		bool rev;
		int sz, ar;
		ll lazy;
		node() {}
		node(int v, int ar_) :
		p(-1), path_p(-1), val(v), sub(v), rev(0), sz(ar_), ar(ar_), lazy(INF) {
			ch[0] = ch[1] = -1;
		}
	};

	node t[2*MAX];
	map<ii, int> mapp;

	void prop(int x) {
		if (t[x].lazy != INF) {
			t[x].val = t[x].lazy, t[x].sub = t[x].lazy;
			if (t[x].ch[0]+1) t[t[x].ch[0]].lazy = t[x].lazy;
			if (t[x].ch[1]+1) t[t[x].ch[1]].lazy = t[x].lazy;
		}
		if (t[x].rev) {
			swap(t[x].ch[0], t[x].ch[1]);
			if (t[x].ch[0]+1) t[t[x].ch[0]].rev ^= 1;
			if (t[x].ch[1]+1) t[t[x].ch[1]].rev ^= 1;
		}
		t[x].lazy = INF, t[x].rev = 0;
	}
	void update(int x) {
		t[x].sz = t[x].ar, t[x].sub = t[x].val;
		for (int i = 0; i < 2; i++) if (t[x].ch[i]+1) {
			prop(t[x].ch[i]);
			t[x].sz += t[t[x].ch[i]].sz;
			t[x].sub = min(t[x].sub, t[t[x].ch[i]].sub);
		}
	}
	void rotate(int x) {
		int p = t[x].p, pp = t[p].p;
		if (pp+1) t[pp].ch[t[pp].ch[1] == p] = x;
		bool d = t[p].ch[0] == x;
		t[p].ch[!d] = t[x].ch[d], t[x].ch[d] = p;
		if (t[p].ch[!d]+1) t[t[p].ch[!d]].p = p;
		t[x].p = pp, t[p].p = x;
		t[x].path_p = t[p].path_p, t[p].path_p = -1;
		update(p), update(x);
	}
	int splay(int x) {
		int r = x;
		vector<int> st = {r};
		while (t[r].p+1) r = t[r].p, st.push_back(r);
		while (st.size()) {
			int u = st.back(); st.pop_back();
			prop(u);
		}
		while (t[x].p+1) {
			int p = t[x].p, pp = t[p].p;
			if (pp == -1) return rotate(x), x;
			if ((t[pp].ch[0] == p)^(t[p].ch[0] == x))
				rotate(x), rotate(x);
			else rotate(p), rotate(x);
		}
		return x;
	}
	int access(int v) {
		splay(v);
		if (t[v].ch[1]+1) {
			t[t[v].ch[1]].path_p = v;
			t[v].ch[1] = t[t[v].ch[1]].p = -1;
			update(v);
		}
		int last = v;
		for (int w; (w=t[v].path_p)+1; update(w), splay(v)) {
			splay(last = w);
			if (t[w].ch[1]+1) {
				t[t[w].ch[1]].path_p = w;
				t[t[w].ch[1]].p = -1;
			}
			t[w].ch[1] = v, t[v].p = w;
		}
		return last;
	}
	void make_tree(int v, int w, int ar=0) { t[v] = node(w, ar); }
	int find_root(int v) {
		access(v);
		while (t[v].ch[0]+1) v = t[v].ch[0];
		return splay(v);
	}
	void rootify(int v) {
		access(v);
		t[v].rev ^= 1;
	}
	ll query(int v, int w) {
		rootify(w), access(v);
		return t[v].sub;
	}
	void update(int v, int w, int x) {
		rootify(w), access(v);
		t[v].lazy = x;
	}
	void link2(int v, int w) {
		rootify(v), access(w);
		t[w].ch[1] = v, t[v].p = w;
		update(w);
	}
	void link(int v, int w, int x) { // v--w com peso x
		int id = MAX+mapp.size();
		mapp[make_pair(v, w)] = id;
		make_tree(id, x, 1);
		link2(v, id), link2(id, w);
	}
	void cut2(int v, int w) {
		rootify(w), access(v);
		t[v].ch[0] = t[t[v].ch[0]].p = -1;
		update(v);
	}
	void cut(int v, int w) {
		int id = mapp[make_pair(v, w)];
		cut2(v, id), cut2(id, w);
	}
	int lca(int v, int w) {
		access(v);
		return access(w);
	}
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i < n; i++) lct::make_tree(i, INF);
	vector<ii> ar;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		ar.pb({a, b});
		lct::link(a, b, 1);
	}
	int m; cin >> m;
	vector<pair<ii, int> > q;
	while (m--) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		q.pb({{a, b}, c});
	}
	sort(q.begin(), q.end(), [](pair<ii, int> a, pair<ii, int> b) {
		return a.s < b.s;
	});
	for (auto i : q) lct::update(i.f.f, i.f.s, i.s);
	for (auto i : q) if (lct::query(i.f.f, i.f.s) != i.s) return cout << -1 << endl, 0;
	for (auto i : ar) cout << lct::query(i.f, i.s) << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

struct dinic {
	struct edge {
		int to, cap, rev, flow; // para, capacidade, id da reversa, fluxo
		bool res; // se a aresta eh residual
		edge(int to_, int cap_, int rev_, bool res_)
			: to(to_), cap(cap_), rev(rev_), flow(0), res(res_) {}
	};

	vector<vector<edge>> g;
	vector<int> lev;
	dinic(int n): g(n){}

	void add(int a, int b, int c=1) { // de a pra b com cap. c
		g[a].pb(edge(b, c, g[b].size(), false));
		g[b].pb(edge(a, 0, g[a].size()-1, true));
	}
	bool bfs(int s, int t) {
		lev = vector<int>(g.size(), -1); lev[s] = 0;
		queue<int> q; q.push(s);
		while (q.size()) {
			int u = q.front(); q.pop();
			for (auto& i : g[u]) {
				if (lev[i.to] != -1 or (i.flow == i.cap)) continue;
				lev[i.to] = lev[u] + 1;
				if (i.to == t) return 1;
				q.push(i.to);
			}
		}
		return 0;
	}
	int dfs(int v, int s, int f = INF){
		if (v == s) return f;
		int tem = f;
		for (auto& i : g[v]) {
			if (lev[i.to] != lev[v] + 1 or (i.flow == i.cap)) continue;
			int foi = dfs(i.to, s, min(tem, i.cap - i.flow));
			tem -= foi, i.flow += foi, g[i.to][i.rev].flow -= foi;
		}
		if (f == tem) lev[v] = -1;
		return f - tem;
	}
	int max_flow(int s, int t) {
		int f = 0;
		while (bfs(s, t)) f += dfs(s, t);
		return f;
	}
	vector<pair<int, int> > get_cut(int s, int t) {
		max_flow(s, t);
		vector<pair<int, int> > cut;
		vector<int> vis(g.size(), 0), st = {s};
		vis[s] = 1;
		while (st.size()) {
			int u = st.back(); st.pop_back();
			for (auto e : g[u]) if (!vis[e.to] and e.flow < e.cap) {
				vis[e.to] = 1;
				st.push_back(e.to);
			}
		}
		for (int i = 0; i < g.size(); i++) for (auto e : g[i])
			if (vis[i] and !vis[e.to] and !e.res) cut.push_back({i, e.to});
		return cut;
	}
};

const int MAX = 5e3+10;

int val[MAX], lev[MAX], pai[MAX], ans[MAX];
vector<int> g[MAX];

void dfs(int k=0, int p=0, int d=0) {
	pai[k] = p;
	lev[k] = d;
	for (int i : g[k]) if (i != p) dfs(i, k, d+1);
}

int main(){ _
	memset(val, INF, sizeof(val));
	int n; cin >> n;
	map<pair<int, int>, int > mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		g[a].pb(b);
		g[b].pb(a);
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
	}
	dfs();
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		qu.pb({{a, b}, c});
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int& x = val[mm[make_pair(a, pai[a])]];
			x = min(x, c);
			a = pai[a];
		}
	}
	dinic d(n-1+q+2);
	for (int i = 0; i < n-1; i++) d.add(n-1+q, i);
	for (int i = 0; i < q; i++) d.add(n-1+i, n+q);
	for (int i = 0; i < q; i++) {
		int a = qu[i].f.f, b = qu[i].f.s;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int ind = mm[make_pair(a, pai[a])];
			if (val[ind] <= qu[i].s) d.add(ind, n-1+i);
			a = pai[a];
		}
	}
	d.max_flow(n-1+q, n+q);
	for (int i = 0; i < n-1; i++) {
		ans[i] = 1e6;
		for (auto e : d.g[i]) if (!e.res and e.flow) ans[i] = qu[e.to-(n-1)].s;
	}
	for (auto i : qu) {
		int a = i.f.f, b = i.f.s;
		int mi = INF;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			mi = min(mi, ans[mm[make_pair(a, pai[a])]]);
			a = pai[a];
		}
		if (mi != i.s) return cout << -1 << endl, 0;
	}
	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

struct dinic {
	struct edge {
		unsigned short to, rev;
		edge(short to_, char cap_, short rev_) : to(to_), rev(rev_) {
			if (cap_) to |= (1<<15);
		}
	};

	vector<vector<edge>> g;
	vector<int> lev;
	dinic(int n): g(n){}

	void add(int a, int b) { // de a pra b com cap. c
		g[a].pb(edge(b, 1, g[b].size()));
		g[b].pb(edge(a, 0, g[a].size()-1));
	}
	bool bfs(int s, int t) {
		lev = vector<int>(g.size(), -1); lev[s] = 0;
		queue<int> q; q.push(s);
		while (q.size()) {
			int u = q.front(); q.pop();
			for (auto& i : g[u]) {
				if (lev[i.to&32767] != -1 or !(i.to>>15)) continue;
				lev[i.to&32767] = lev[u] + 1;
				if ((i.to&32767) == t) return 1;
				q.push(i.to&32767);
			}
		}
		return 0;
	}
	int dfs(int v, int s, int f = INF){
		if (v == s) return f;
		int tem = f;
		for (auto& i : g[v]) {
			if (lev[i.to&32767] != lev[v] + 1 or !(i.to>>15)) continue;
			int foi = dfs(i.to&32767, s, min(tem, i.to>>15));
			if (foi) {
				tem -= foi;
				i.to ^= (1<<15);
				g[i.to&32767][i.rev].to ^= (1<<15);
			}
		}
		if (f == tem) lev[v] = -1;
		return f - tem;
	}
	int max_flow(int s, int t) {
		int f = 0;
		while (bfs(s, t)) f += dfs(s, t);
		return f;
	}
};

const int MAX = 5e3+10;

int val[MAX], lev[MAX], pai[MAX], ans[MAX];
vector<int> g[MAX];

void dfs(int k=0, int p=0, int d=0) {
	pai[k] = p;
	lev[k] = d;
	for (int i : g[k]) if (i != p) dfs(i, k, d+1);
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i < n-1; i++) val[i] = 1;
	map<pair<int, int>, int > mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		g[a].pb(b);
		g[b].pb(a);
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
	}
	dfs();
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		qu.pb({{a, b}, c});
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int& x = val[mm[make_pair(a, pai[a])]];
			x = max(x, c);
			a = pai[a];
		}
	}
//	for (int i = 0; i < n-1; i++) cout << val[i] << " ";
//	cout << endl;
	static dinic d(n-1+q+2);
	for (int i = 0; i < n-1; i++) d.add(n-1+q, i);
	for (int i = 0; i < q; i++) d.add(n-1+i, n+q);
	for (int i = 0; i < q; i++) {
		int a = qu[i].f.f, b = qu[i].f.s;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int ind = mm[make_pair(a, pai[a])];
			if (val[ind] <= qu[i].s) d.add(ind, n-1+i);
			a = pai[a];
		}
	}
	d.max_flow(n-1+q, n+q);
	for (int i = 0; i < n-1; i++) {
		ans[i] = 1e6;
		for (auto e : d.g[i]) if ((e.to&32767) != n-1+q and !(e.to>>15)) ans[i] = qu[e.to-(n-1)].s;
	}
//	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
//	cout << endl;
	for (auto i : qu) {
		int a = i.f.f, b = i.f.s;
		int mi = INF;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			mi = min(mi, ans[mm[make_pair(a, pai[a])]]);
			a = pai[a];
		}
		if (mi != i.s) return cout << -1 << endl, 0;
	}
	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

struct dinic {
	struct edge {
		unsigned short to, rev;
		edge(short to_, char cap_, short rev_) : to(to_), rev(rev_) {
			if (cap_) to |= (1<<15);
		}
	};

	vector<vector<edge>> g;
	vector<int> lev;
	dinic(int n): g(n){}

	void add(int a, int b) { // de a pra b com cap. c
		g[a].pb(edge(b, 1, g[b].size()));
		g[b].pb(edge(a, 0, g[a].size()-1));
	}
	bool bfs(int s, int t) {
		lev = vector<int>(g.size(), -1); lev[s] = 0;
		queue<int> q; q.push(s);
		while (q.size()) {
			int u = q.front(); q.pop();
			for (auto& i : g[u]) {
				if (lev[i.to&32767] != -1 or !(i.to>>15)) continue;
				lev[i.to&32767] = lev[u] + 1;
				if ((i.to&32767) == t) return 1;
				q.push(i.to&32767);
			}
		}
		return 0;
	}
	int dfs(int v, int s, int f = INF){
		if (v == s) return f;
		int tem = f;
		for (auto& i : g[v]) {
			if (lev[i.to&32767] != lev[v] + 1 or !(i.to>>15)) continue;
			int foi = dfs(i.to&32767, s, min(tem, i.to>>15));
			if (foi) {
				tem -= foi;
				i.to ^= (1<<15);
				g[i.to&32767][i.rev].to ^= (1<<15);
			}
		}
		if (f == tem) lev[v] = -1;
		return f - tem;
	}
	int max_flow(int s, int t) {
		int f = 0;
		while (bfs(s, t)) f += dfs(s, t);
		return f;
	}
};

const int MAX = 5e3+10;

int val[MAX], lev[MAX], pai[MAX], ans[MAX];
vector<int> g[MAX];

void dfs(int k=0, int p=0, int d=0) {
	pai[k] = p;
	lev[k] = d;
	for (int i : g[k]) if (i != p) dfs(i, k, d+1);
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i < n-1; i++) val[i] = 1;
	map<pair<int, int>, int > mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		g[a].pb(b);
		g[b].pb(a);
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
	}
	dfs();
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		qu.pb({{a, b}, c});
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int& x = val[mm[make_pair(a, pai[a])]];
			x = max(x, c);
			a = pai[a];
		}
	}
//	for (int i = 0; i < n-1; i++) cout << val[i] << " ";
//	cout << endl;
	dinic d(n-1+q+2);
	for (int i = 0; i < n-1; i++) d.add(n-1+q, i);
	for (int i = 0; i < q; i++) d.add(n-1+i, n+q);
	for (int i = 0; i < q; i++) {
		int a = qu[i].f.f, b = qu[i].f.s;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int ind = mm[make_pair(a, pai[a])];
			if (val[ind] <= qu[i].s) d.add(ind, n-1+i);
			a = pai[a];
		}
	}
	d.max_flow(n-1+q, n+q);
	for (int i = 0; i < n-1; i++) {
		ans[i] = 1e6;
		for (auto e : d.g[i]) if ((e.to&32767) != n-1+q and !(e.to>>15)) ans[i] = qu[e.to-(n-1)].s;
	}
//	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
//	cout << endl;
	for (auto i : qu) {
		int a = i.f.f, b = i.f.s;
		int mi = INF;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			mi = min(mi, ans[mm[make_pair(a, pai[a])]]);
			a = pai[a];
		}
		if (mi != i.s) return cout << -1 << endl, 0;
	}
	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

const int MAX = 5e3+10;

vector<vector<int> > g(MAX);
int in[MAX], h[MAX], sz[MAX];
int pai[MAX], t;

void build(int k, int p = -1, int f = 1) {
	in[k] = t++; sz[k] = 1;
	for (int& i : g[k]) if (i != p) {
		pai[i] = k;
		h[i] = (i == g[k][0] ? h[k] : i);
		build(i, k, f); sz[k] += sz[i];

		if (sz[i] > sz[g[k][0]]) swap(i, g[k][0]);
	}
	if (p*f == -1) t = 0, h[k] = k, build(k, -1, 0);
}

int lca(int a, int b) {
	if (in[a] < in[b]) swap(a, b);
	return h[a] == h[b] ? b : lca(pai[h[a]], b);
}

int val[MAX], val2[MAX], ans[MAX];

int dfs(int k, int p=-1) {
	val2[k] = val[k];
	for (int i : g[k]) if (i != p) val2[k] += dfs(i, k);
	return val2[k];
}

int main(){ _
	int n; cin >> n;
	for (int i = 0; i <= n; i++) ans[i] = 1;
	map<pair<int, int>, int> mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
		g[a].pb(b);
		g[b].pb(a);
	}
	build(0);
	pai[0] = 0;
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, m; cin >> a >> b >> m;
		a--, b--;
		qu.pb({{a, b}, m});
	}
	sort(qu.begin(), qu.end(), [](pair<ii, int> a, pair<ii, int> b){ return a.s < b.s; });
	for (int i = 0; i < q; i++) {
		//cout << "---- " << i << endl;
		memset(val, 0, sizeof(val));
		memset(val2, 0, sizeof(val2));
		for (int j = i+1; j < q; j++) if (qu[j].s > qu[i].s) {
			int a, b;
			tie(a, b) = qu[j].f;
			//cout << "colocando no " << a << " " << b << endl;
			val[a]++;
			val[b]++;
			int l = lca(a, b);
			if (pai[l] != l) val[pai[l]] -= 2;
		}
		dfs(0);
		int a, b;
		tie(a, b) = qu[i].f;
		int l = lca(a, b);
		bool deu = 0;
		while (a != l) {
			if (!val2[a]) {
				ans[a] = qu[i].s;
				deu = 1;
			}
			a = pai[a];
		}
		while (b != l) {
			if (!val2[b]) {
				ans[b] = qu[i].s;
				deu = 1;
			}
			b = pai[b];
		}
		if (!deu) return cout << -1 << endl, 0;
	}
	vector<int> anss(n-1, 1);
	for (int i = 0; i < n; i++) if (pai[i] != i) {
		int x = ans[i];
		anss[mm[make_pair(i, pai[i])]] = x;
	}
	for (int i = 0; i < n-1; i++) cout << anss[i] << " ";
	cout << endl;
	exit(0);
}


#include <bits/stdc++.h>

using namespace std;

#define _ ios_base::sync_with_stdio(0);cin.tie(0);
//#define endl '\n'
#define f first
#define s second
#define pb push_back

typedef long long ll;
typedef pair<int, int> ii;

const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3fll;

struct dinic {
	struct edge {
		int to, cap, rev, flow; // para, capacidade, id da reversa, fluxo
		bool res; // se a aresta eh residual
		edge(int to_, int cap_, int rev_, bool res_)
			: to(to_), cap(cap_), rev(rev_), flow(0), res(res_) {}
	};

	vector<vector<edge>> g;
	vector<int> lev;
	dinic(int n): g(n){}

	void add(int a, int b, int c=1) { // de a pra b com cap. c
		g[a].pb(edge(b, c, g[b].size(), false));
		g[b].pb(edge(a, 0, g[a].size()-1, true));
	}
	bool bfs(int s, int t) {
		lev = vector<int>(g.size(), -1); lev[s] = 0;
		queue<int> q; q.push(s);
		while (q.size()) {
			int u = q.front(); q.pop();
			for (auto& i : g[u]) {
				if (lev[i.to] != -1 or (i.flow == i.cap)) continue;
				lev[i.to] = lev[u] + 1;
				if (i.to == t) return 1;
				q.push(i.to);
			}
		}
		return 0;
	}
	int dfs(int v, int s, int f = INF){
		if (v == s) return f;
		int tem = f;
		for (auto& i : g[v]) {
			if (lev[i.to] != lev[v] + 1 or (i.flow == i.cap)) continue;
			int foi = dfs(i.to, s, min(tem, i.cap - i.flow));
			tem -= foi, i.flow += foi, g[i.to][i.rev].flow -= foi;
		}
		if (f == tem) lev[v] = -1;
		return f - tem;
	}
	int max_flow(int s, int t) {
		int f = 0;
		while (bfs(s, t)) f += dfs(s, t);
		return f;
	}
	vector<pair<int, int> > get_cut(int s, int t) {
		max_flow(s, t);
		vector<pair<int, int> > cut;
		vector<int> vis(g.size(), 0), st = {s};
		vis[s] = 1;
		while (st.size()) {
			int u = st.back(); st.pop_back();
			for (auto e : g[u]) if (!vis[e.to] and e.flow < e.cap) {
				vis[e.to] = 1;
				st.push_back(e.to);
			}
		}
		for (int i = 0; i < g.size(); i++) for (auto e : g[i])
			if (vis[i] and !vis[e.to] and !e.res) cut.push_back({i, e.to});
		return cut;
	}
};

const int MAX = 5e3+10;

int val[MAX], lev[MAX], pai[MAX], ans[MAX];
vector<int> g[MAX];

void dfs(int k=0, int p=0, int d=0) {
	pai[k] = p;
	lev[k] = d;
	for (int i : g[k]) if (i != p) dfs(i, k, d+1);
}

int main(){ _
	memset(val, INF, sizeof(val));
	int n; cin >> n;
	map<pair<int, int>, int > mm;
	for (int i = 0; i < n-1; i++) {
		int a, b; cin >> a >> b; a--, b--;
		g[a].pb(b);
		g[b].pb(a);
		mm[make_pair(a, b)] = i;
		mm[make_pair(b, a)] = i;
	}
	dfs();
	int q; cin >> q;
	vector<pair<ii, int> > qu;
	for (int i = 0; i < q; i++) {
		int a, b, c; cin >> a >> b >> c; a--, b--;
		qu.pb({{a, b}, c});
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int& x = val[mm[make_pair(a, pai[a])]];
			x = min(x, c);
			a = pai[a];
		}
	}
	dinic d(n-1+q+2);
	for (int i = 0; i < n-1; i++) d.add(n-1+q, i);
	for (int i = 0; i < q; i++) d.add(n-1+i, n+q);
	for (int i = 0; i < q; i++) {
		//if (val[i] <= qu[j].s) d.add(i, n-1+j);
		int a = qu[i].f.f, b = qu[i].f.s;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			int ind = mm[make_pair(a, pai[a])];
			if (val[ind] <= qu[i].s) d.add(ind, n-1+i);
			a = pai[a];
		}
	}
	d.max_flow(n-1+q, n+q);
	for (int i = 0; i < n-1; i++) {
		ans[i] = 1;
		for (auto e : d.g[i]) if (!e.res and e.flow) ans[i] = qu[e.to-(n-1)].s;
	}
	for (auto i : qu) {
		int a = i.f.f, b = i.f.s;
		int mi = INF;
		while (a != b) {
			if (lev[a] < lev[b]) swap(a, b);
			mi = min(mi, ans[mm[make_pair(a, pai[a])]]);
			a = pai[a];
		}
		if (mi != i.s) return cout << -1 << endl, 0;
	}
	for (int i = 0; i < n-1; i++) cout << ans[i] << " ";
	cout << endl;
	exit(0);
}