#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<ll> vll;

#define ordered_set tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
#define ordered_multiset tree<int, null_type, less_equal<int>, rb_tree_tag, tree_order_statistics_node_update>
#define pb push_back
#define ff first
#define ss second

const int N = 3e5 + 5;

vi graf[N], sciezka, trasa;
vll ile;

ll A[N], B[N];
int c[N], oryg[N], czy[N], dp1[N], dp2[N];

int best, start;

bool cmp(int a, int b){
    return c[a] > c[b];
}

void dfs(int v, int ojc){
    c[v] = oryg[v];
    czy[v] = (c[v] == 0);
    dp1[v] = 0;
    dp2[v] = -1;

    for(int u : graf[v]){
        if(u == ojc) continue;

        dfs(u, v);

        c[v] += c[u];
        czy[v] &= czy[u];

        int kand = dp1[u] + 1 - 2 * (c[u] > 0);

        if(!czy[u] && kand >= dp1[v]){
            dp1[v] = kand;
            dp2[v] = u;
        }
    }

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

        if(u == ojc) continue;

        if(czy[u]){
            swap(graf[v][i], graf[v].back());
            graf[v].pop_back();
            i--;
        }
    }
}

void dfs2(int v, int ojc, int up){
    if(c[v] < 0) up -= 2;

    int kand = max(dp1[v], up);

    if(kand > best){
        best = kand;
        start = v;
    }

    int m = graf[v].size();

    vi pref(m + 1, 0), suf(m + 1, 0);

    for(int i = 0; i < m; i++){
        pref[i + 1] = pref[i];

        int u = graf[v][i];

        if(u == ojc) continue;

        int kand2 = dp1[u] + 1 - 2 * (c[u] > 0);

        pref[i + 1] = max(pref[i + 1], kand2);
    }

    for(int i = m - 1; i >= 0; i--){
        suf[i] = suf[i + 1];

        int u = graf[v][i];

        if(u == ojc) continue;

        int kand2 = dp1[u] + 1 - 2 * (c[u] > 0);

        suf[i] = max(suf[i], kand2);
    }

    for(int i = 0; i < m; i++){
        int u = graf[v][i];

        if(u == ojc) continue;

        int nast = max({pref[i], suf[i + 1], up}) + 1;

        dfs2(u, v, nast);
    }
}

void odz(int v){
    sciezka.pb(v);

    if(dp2[v] == -1) return;

    odz(dp2[v]);
}

void dfs3(int v, int ojc){
    sort(graf[v].begin(), graf[v].end(), cmp);

    trasa.pb(v);
    ile.pb(-A[v]);

    for(int u : graf[v]){
        if(u == ojc) continue;

        dfs3(u, v);

        trasa.pb(v);
        ile.pb(0);
    }

    ile.back() += B[v];
}

void solve(){
    int n;
    cin >> n;

    best = -1;
    start = -1;

    sciezka.clear();
    trasa.clear();
    ile.clear();

    for(int i = 1; i <= n; i++){
        graf[i].clear();
        czy[i] = 0;
        c[i] = 0;
        oryg[i] = 0;
        dp1[i] = 0;
        dp2[i] = -1;
    }

    for(int i = 1; i <= n; i++)
        cin >> A[i];

    for(int i = 1; i <= n; i++)
        cin >> B[i];

    for(int i = 1; i <= n; i++){
        // Trzymamy dokładnie tę samą konwencję co bike.h:
        // d = A - B
        oryg[i] = A[i] - B[i];
        c[i] = oryg[i];
    }

    for(int i = 1; i < n; i++){
        int a, b;
        cin >> a >> b;

        // input ma numery 0..n-1
        ++a;
        ++b;

        graf[a].pb(b);
        graf[b].pb(a);
    }

    int root = -1;

    for(int i = 1; i <= n; i++){
        if(A[i] != B[i]){
            root = i;
            break;
        }
    }

    // Wszystko już jest poprawne.
    if(root == -1){
        cout << "0\n";
        cout << "0\n";
        cout << "0\n";
        return;
    }

    // Pierwszy DP
    dfs(root, 0);

    // Szukamy najlepszego początku głównej ścieżki
    dfs2(root, 0, 0);

    // Drugi DFS od znalezionego początku
    // i odbudowanie c jako bilansów poddrzew
    for(int i = 1; i <= n; i++){
        c[i] = oryg[i];
        czy[i] = 0;
        dp1[i] = 0;
        dp2[i] = -1;
    }

    dfs(start, 0);

    // Odtwarzamy główną ścieżkę
    sciezka.clear();

    for(int v = start; v != -1; v = dp2[v])
        sciezka.pb(v);

    /*
        Usuwamy krawędzie głównej ścieżki.
        To jest dokładnie to, co robi oryginalny kod bike.h.
    */
    for(int i = 1; i < (int)sciezka.size(); i++){
        int x = sciezka[i - 1];
        int y = sciezka[i];

        auto it1 = find(graf[x].begin(), graf[x].end(), y);
        graf[x].erase(it1);

        auto it2 = find(graf[y].begin(), graf[y].end(), x);
        graf[y].erase(it2);
    }

    /*
        Budowanie konkretnej trasy.
    */
    int m = sciezka.size();

    for(int i = 0; i < m; i++){
        if(i + 1 == m || c[sciezka[i + 1]] <= 0){

            int j = i - 1;

            while(j >= 0 && c[sciezka[j + 1]] > 0)
                j--;

            for(int k = i; k > j; k--)
                dfs3(sciezka[k], -1);

            for(int k = j + 2; k <= i; k++){
                trasa.pb(sciezka[k]);
                ile.pb(0);
            }
        }
        else{
            trasa.pb(sciezka[i]);
            ile.pb(0);
        }
    }

    int koszt = (int)trasa.size() - 1;

    cout << koszt << '\n';

    // z powrotem na numerację 0..n-1
    for(int i = 0; i < (int)trasa.size(); i++){
        if(i) cout << ' ';
        cout << trasa[i] - 1;
    }
    cout << '\n';

    for(int i = 0; i < (int)ile.size(); i++){
        if(i) cout << ' ';
        cout << ile[i];
    }
    cout << '\n';
}

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

    int t;
    cin >> t;

    while(t--)
        solve();

    return 0;
}