#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define ls(x) x * 2 + 1
#define rs(x) x * 2 + 2
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int INF = (int)1e9;

const int N = (int)1e6 + 50;

struct edge {
    int to, w, id;
};

int tin[N], tout[N], tim = 0;
int val[N];
int pr[N];
int nid[N];

struct node {
    int cr;
    int abmax;
    int a, b;
    int abmax_pre[2], abmax_suf[2];
    int amb_suf[2], bma_pre[2];

    void flip() {
        cr ^= 1;
        swap(abmax_pre[0], abmax_pre[1]);
        swap(abmax_suf[0], abmax_suf[1]);
        swap(amb_suf[0], amb_suf[1]);
        swap(bma_pre[0], bma_pre[1]);
    }

    void merge(node &ls, node &rs) {
        abmax = 0;
        rep(p, 0, 2) {
//            if(p == 0) cout << ls.abmax_suf[p] << " " << rs.bma_pre[p] << " " << ls.amb_suf[p] << " " << rs.abmax_pre[p] << endl;
            abmax = max({abmax, ls.abmax_suf[p] + rs.bma_pre[p], ls.amb_suf[p] + rs.abmax_pre[p]});
//            cout << abmax << endl;

            abmax_pre[p] = max(ls.abmax_pre[p], max(ls.a + ls.b + rs.bma_pre[p], ls.a - ls.b + rs.abmax_pre[p]));
            abmax_suf[p] = max(max(ls.amb_suf[p] + rs.a + rs.b, ls.abmax_suf[p] + rs.b - rs.a), rs.abmax_suf[p]);
            amb_suf[p] = max(ls.amb_suf[p] + rs.a - rs.b, rs.amb_suf[p]);
            bma_pre[p] = max(ls.bma_pre[p], ls.b - ls.a + rs.bma_pre[p]);
        }

        abmax = max(abmax, max(ls.abmax, rs.abmax));
        a = ls.a + max(0, rs.a - ls.b);
        b = max(0, ls.b - rs.a) + rs.b;
    }
};

node newnode(int v, int d) {
    if(!d) return {0, 0, !v, v,
                   {1, -INF}, {1, -INF},
                   {!v ? 1 : -INF, -INF}, {v ? 1 : -INF, -INF}};
    else return {0, 0, !v, v,
                 {-INF, 1}, {-INF, 1},
                 {-INF, !v ? 1 : -INF}, {-INF, v ? 1 : -INF}};
}

struct Tree {
    node dat[4 * N];

    void push_down(int x, int l, int r) {
        if(dat[x].cr) {
            if(l < r) {
                dat[ls(x)].flip();
                dat[rs(x)].flip();
            }
            dat[x].cr = 0;
        }
    }

    void init(int x, int l, int r) {
        if(l == r) {
            dat[x] = newnode(val[l], pr[l]);
            return ;
        }
        int mid = (l + r) / 2;
        init(ls(x), l, mid);
        init(rs(x), mid + 1, r);
        dat[x].merge(dat[ls(x)], dat[rs(x)]);
//        cout << x << " " << l << " " << r << ": " << dat[x].abmax << endl;
    }

    void update(int a, int b, int x, int l, int r) {
        int mid = (l + r) / 2;
        if(r < a || l > b) return ;

        push_down(x, l, r);

        if(l >= a && r <= b) {
            dat[x].flip();
            return ;
        }

        update(a, b, ls(x), l, mid);
        update(a, b, rs(x),mid+1, r);

        dat[x].merge(dat[ls(x)], dat[rs(x)]);
    }

} tree;

int n, m;
vector<edge> G[N];

void dfs(int v, int p, int d) {
    val[tim] = 1;
    pr[tim] = d;
    tin[v] = tim++;

    for(auto e : G[v]) {
        if(e.to == p) continue;
        nid[e.id] = e.to;
        dfs(e.to, v, d ^ e.w);
    }

    val[tim] = 0;
    pr[tim] = d;
    tout[v] = tim++;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n;
    rep(i, 0, n - 1) {
        int a, b, w;
        cin >> a >> b >> w;
        a--, b--;
        G[a].push_back({b, w, i});
        G[b].push_back({a, w, i});
    }
    dfs(0, -1, 0);
    tree.init(0, 1, 2 * n - 2);

    cin >> m;
//    cout << tree.dat[0].abmax << " " <<  tree.dat[0].abmax_pre[0] << " " <<  tree.dat[0].abmax_suf[0] << '\n';

    rep(i, 0, m) {
        int id; cin >> id; id--;
        int v = nid[id];
        tree.update(tin[v], tout[v], 0, 1, 2 * n - 2);
        cout << max(tree.dat[0].abmax, max(tree.dat[0].abmax_pre[0], tree.dat[0].abmax_suf[0])) << '\n';
    }

}


#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define ls(x) x * 2 + 1
#define rs(x) x * 2 + 2
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int INF = (int)1e9;

const int N = (int)1e6 + 50;

struct edge {
    int to, w, id;
};

int n, m;
vector<edge> G[N];

struct node {
    int cr;
    int mx[2];

    void flip() {
        cr ^= 1;
        swap(mx[0], mx[1]);
    }

    void merge(node &ls, node &rs) {
        rep(p, 0, 2) mx[p] = max(ls.mx[p], rs.mx[p]);
    }
};

struct Tree {
    node dat[4 * N];
    int root;
    int tin[N], tout[N], tim = 0;
    int nid[N], pr[N];
    int dep[N];

    void dfs(int v, int p, int d, int depth) {
        pr[tim] = d;
        dep[tim] = depth;
        tin[v] = tim++;
        for(auto e : G[v]) {
            if(e.to == p) continue;
            nid[e.id] = e.to;
            dfs(e.to, v, d ^ e.w, depth + 1);
        }
        tout[v] = tim - 1;
    }

    void push_down(int x, int l, int r) {
        if(dat[x].cr) {
            if(l < r) {
                dat[ls(x)].flip();
                dat[rs(x)].flip();
            }
            dat[x].cr = 0;
        }
    }

    void init(int x, int l, int r) {
        if(l == r) {
            dat[x] = pr[l] ? node{0, {0, dep[l]}} :
                    node{0, {dep[l] , 0}};
            return ;
        }
        int mid = (l + r) / 2;
        init(ls(x), l, mid);
        init(rs(x), mid + 1, r);
        dat[x].merge(dat[ls(x)], dat[rs(x)]);
//        cout << x << " " << l << " " << r << ": " << dat[x].abmax << endl;
    }

    void update(int a, int b, int x, int l, int r) {
        int mid = (l + r) / 2;
        if(r < a || l > b) return ;

        push_down(x, l, r);

        if(l >= a && r <= b) {
            dat[x].flip();
            return ;
        }

        update(a, b, ls(x), l, mid);
        update(a, b, rs(x),mid+1, r);

        dat[x].merge(dat[ls(x)], dat[rs(x)]);
    }

    void update(int eid) {
        update(tin[nid[eid]], tout[nid[eid]], 0, 0, n - 1);
    }

} tree[2];

pii dfs(int v, int p) {
    pii res = {0, v};
    for(auto e : G[v]) {
        if(e.to != p) {
            pii nxt = dfs(e.to, v);
            res = max(res, {nxt.first + 1, nxt.second});
        }
    }
    return res;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n;
    rep(i, 0, n - 1) {
        int a, b, w;
        cin >> a >> b >> w;
        a--, b--;
        G[a].push_back({b, w, i});
        G[b].push_back({a, w, i});
    }
    pii p = dfs(0, -1);
    tree[0].root = p.second;
    p = dfs(p.second, -1);
    tree[1].root = p.second;

//    cout << "?" << endl;

    rep(it, 0, 2) {
        tree[it].dfs(tree[it].root, -1, 0, 0);
        tree[it].init(0, 0, n - 1);
    }
//    cout << "?" << endl;
    cin >> m;
//    cout << tree.dat[0].abmax << " " <<  tree.dat[0].abmax_pre[0] << " " <<  tree.dat[0].abmax_suf[0] << '\n';

    rep(i, 0, m) {
        int id; cin >> id; id--;
        tree[0].update(id);
        tree[1].update(id);
        cout << max(tree[0].dat[0].mx[0], tree[1].dat[0].mx[0]) << '\n';
    }

}


#include <bits/stdc++.h>
using namespace std;

#define rep(i, a, b) for(int i = a; i < (b); ++i)
#define trav(a, x) for(auto& a : x)
#define all(x) begin(x), end(x)
#define sz(x) (int)(x).size()
#define ls(x) x * 2 + 1
#define rs(x) x * 2 + 2
typedef long long ll;
typedef pair<int, int> pii;
typedef vector<int> vi;
const int INF = (int)1e9;

const int N = (int)1e6 + 50;

struct edge {
    int to, w, id;
};

int tin[N], tout[N], tim = 0;
int val[N];
int pr[N];
int nid[N];

struct node {
    int cr;
    int abmax;
    int a, b;
    int abmax_pre[2], abmax_suf[2];
    int amb_suf[2], bma_pre[2];

    void flip() {
        cr ^= 1;
        swap(abmax_pre[0], abmax_pre[1]);
        swap(abmax_suf[0], abmax_suf[1]);
        swap(amb_suf[0], amb_suf[1]);
        swap(bma_pre[0], bma_pre[1]);
    }

    void merge(node &ls, node &rs) {
        abmax = 0;
        rep(p, 0, 2) {
//            if(p == 0) cout << ls.abmax_suf[p] << " " << rs.bma_pre[p] << " " << ls.amb_suf[p] << " " << rs.abmax_pre[p] << endl;
            abmax = max({abmax, ls.abmax_suf[p] + rs.bma_pre[p], ls.amb_suf[p] + rs.abmax_pre[p]});
//            cout << abmax << endl;

            abmax_pre[p] = max(ls.abmax_pre[p], max(ls.a + ls.b + rs.bma_pre[p], ls.a - ls.b + rs.abmax_pre[p]));
            abmax_suf[p] = max(max(ls.amb_suf[p] + rs.a + rs.b, ls.abmax_suf[p] + rs.b - rs.a), rs.abmax_suf[p]);
            amb_suf[p] = max(ls.amb_suf[p] + rs.a - rs.b, rs.amb_suf[p]);
            bma_pre[p] = max(ls.bma_pre[p], ls.b - ls.a + rs.bma_pre[p]);
        }

        abmax = max(abmax, max(ls.abmax, rs.abmax));
        a = ls.a + max(0, rs.a - ls.b);
        b = max(0, ls.b - rs.a) + rs.b;
    }
};

node newnode(int v, int d) {
    if(!d) return {0, 1, !v, v,
                   {1, -INF}, {1, -INF},
                   {!v, -INF}, {v, -INF}};
    else return {0, 1, !v, v,
                 {-INF, 1}, {-INF, 1},
                 {-INF, !v}, {-INF, v}};
}

struct Tree {
    node dat[4 * N];

    void push_down(int x, int l, int r) {
        if(dat[x].cr) {
            if(l < r) {
                dat[ls(x)].flip();
                dat[rs(x)].flip();
            }
            dat[x].cr = 0;
        }
    }

    void init(int x, int l, int r) {
        if(l == r) {
            dat[x] = newnode(val[l], pr[l]);
            return ;
        }
        int mid = (l + r) / 2;
        init(ls(x), l, mid);
        init(rs(x), mid + 1, r);
        dat[x].merge(dat[ls(x)], dat[rs(x)]);
//        cout << x << " " << l << " " << r << ": " << dat[x].abmax << endl;
    }

    void update(int a, int b, int x, int l, int r) {
        int mid = (l + r) / 2;
        if(r < a || l > b) return ;

        push_down(x, l, r);

        if(l >= a && r <= b) {
            dat[x].flip();
            return ;
        }

        update(a, b, ls(x), l, mid);
        update(a, b, rs(x),mid+1, r);

        dat[x].merge(dat[ls(x)], dat[rs(x)]);
    }

} tree;

int n, m;
vector<edge> G[N];

void dfs(int v, int p, int d) {
    val[tim] = 1;
    pr[tim] = d;
    tin[v] = tim++;

    for(auto e : G[v]) {
        if(e.to == p) continue;
        nid[e.id] = e.to;
        dfs(e.to, v, d ^ e.w);
    }

    val[tim] = 0;
    pr[tim] = d;
    tout[v] = tim++;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(NULL);

    cin >> n;
    rep(i, 0, n - 1) {
        int a, b, w;
        cin >> a >> b >> w;
        a--, b--;
        G[a].push_back({b, w, i});
        G[b].push_back({a, w, i});
    }
    dfs(0, -1, 0);
    tree.init(0, 1, 2 * n - 2);
//    rep(i, 0, tim) cout << val[i] << " ";
//    cout << endl;
//    rep(i, 0, tim) cout << pr[i] << " ";
//    cout << endl;
//    cout << tree.dat[0].abmax << '\n';

    cin >> m;

    rep(i, 0, m) {
        int id; cin >> id; id--;
        int v = nid[id];
        tree.update(tin[v], tout[v], 0, 1, 2 * n - 2);
        cout << tree.dat[0].abmax << '\n';
    }

}


@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")
@file:OptIn(ExperimentalStdlibApi::class)

import java.io.PrintWriter
import kotlin.math.*
import kotlin.random.Random
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
//    val startTime = System.nanoTime()

    val numCases = 1//readInt()
    case@ for(case in 1..numCases) {
        //print("Case #$case: ")

       object {
           val n = readInt()
           val G = Array(n) { IntList() }

           val U = IntArray(n-1)
           val V = IntArray(n-1)
           val T = BooleanArray(n-1) { i ->
               U[i] = readInt()-1
               V[i] = readInt()-1

               G[U[i]].add(V[i])
               G[V[i]].add(U[i])

               readInt() == 1
           }

           fun deps(r: Int): IntArray {
               val dep = IntArray(n) { -1 }
               dep[r] = 0
               val stk = intListOf(r)

               while(stk.isNotEmpty()) {
                   val u = stk.pop()
                   for(v in G[u]) if(dep[v] == -1) {
                       dep[v] = dep[u] + 1
                       stk.add(v)
                   }
               }

               return dep
           }

           inner class EulTree(val r: Int) {
               val dep = IntArray(n) { -1 }
               val tree = PropagatingSegmentTree(n, dep)

               val start = IntArray(n)
               val end = IntArray(n)
               init {
                   dep[r] = 0
                   val stk = intListOf(r)
                   val A = SegArray(n)
                   var i = 0

                   while(stk.isNotEmpty()) {
                       var u = stk.pop()
                       if(u >= 0) {
                           stk.add(u.inv())
                           A[i] = Seg(u, -1)
                           start[u] = i++

                           for(v in G[u]) if(dep[v] == -1) {
                               dep[v] = dep[u] + 1
                               stk.add(v)
                           }
                       } else {
                           u = u.inv()
                           end[u] = i
                       }
                   }

                   tree.build(A::get)
               }

               fun flip(ei: Int) {
                   val u = if(dep[U[ei]] > dep[V[ei]]) U[ei] else V[ei]
                   tree.update(start[u], end[u], true)
               }

               fun bestDep() = dep[tree.root.best0]
           }

           val e0 = run {
               val d0 = deps(0)
               val i = d0.indexOf(d0.max())

               EulTree(i)
           }

           val e1 = run {
               val d0 = e0.dep
               val i = d0.indexOf(d0.max())

               EulTree(i)
           }

           init {
               for(i in 0 until n-1) {
                   if(T[i]) {
                       e0.flip(i)
                       e1.flip(i)
                   }
               }

               val m = readInt()
               repeat(m) {
                   val i = readInt()-1
                   e0.flip(i)
                   e1.flip(i)

                   val ans = max(e0.bestDep(), e1.bestDep())
                   println(ans)
               }
           }

       }
    }

//    iprintln("Time: ${(System.nanoTime() - startTime) / 1000000} ms")
}

class PropagatingSegmentTree(
    val size: Int,
    val dep: IntArray
//        val identityValue: T,
//        val op: (T, T) -> T,
//        val updateIdentity: U,
//        val composer: (U, U) -> U,
//        val updater: (T, U) -> T
) {
    fun best(u: Int, v: Int) = when {
        u == -1 -> v
        v == -1 -> u
        dep[u] > dep[v] -> u
        else -> v
    }

    inline val identityValue: Seg get() = Seg(-1, -1)
    inline fun op(a: Seg, b: Seg): Seg = Seg(best(a.best0, b.best0), best(a.best1, b.best1))
    inline val updateIdentity: Boolean get() = false
    inline fun composer(a: Boolean, b: Boolean): Boolean = a xor b
    inline fun updater(t: Seg, u: Boolean): Seg = if(!u) t else Seg(t.best1, t.best0)

    val tsize = if(size == 0) 0 else Integer.highestOneBit(size.shl(1) - 1)

    @Suppress("UNCHECKED_CAST")
    val A = SegArray(tsize shl 1) { identityValue }
    @Suppress("UNCHECKED_CAST")
    val B = BooleanArray(tsize) //{ updateIdentity } as Array<Boolean>

    private val h = 32 - Integer.numberOfLeadingZeros(tsize)

    inline fun build(generator: (Int) -> Seg) {
        for(i in 0 until size) {
            A[tsize+i] = generator(i)
        }
        for(i in tsize-1 downTo 1) {
            A[i] = op(A[i shl 1], A[i shl 1 or 1])
        }
    }

    private fun calc(i: Int) {
        A[i] = op(A[i shl 1], A[i shl 1 or 1])
        A[i] = updater(A[i], B[i])
    }

    private fun apply(i: Int, u: Boolean) {
        A[i] = updater(A[i], u)
        if(i < tsize) {
            B[i] = composer(B[i], u)
        }
    }

    private fun build(l: Int) {
        //var k = 2
        var l = l
        while(l > 1) {
            l = l shr 1
            calc(l)
            //k = k shl 1
        }
    }

    private fun push(l: Int) {
        var s = h
        //var k = 1 shl h-1
        while(s > 0) {
            val i = l shr s

            val b = B[i]
            if(b != updateIdentity) {
                apply(i shl 1, b)
                apply(i shl 1 or 1, b)
                B[i] = updateIdentity
            }

            s--
            //k = k shr 1
        }
    }

    fun update(start: Int, endExclusive: Int, b: Boolean) {
        var l = maxOf(start, 0) + tsize
        var r = minOf(endExclusive, size) + tsize

        push(l)
        push(r-1)
        val l0 = l
        val r0 = r

        //var k = 1

        while(l < r) {
            if(l and 1 == 1) {
                apply(l++, b)
            }
            if(r and 1 == 1) {
                apply(--r, b)
            }

            l = l shr 1
            r = r shr 1
            //k = k shl 1
        }

        build(l0)
        build(r0-1)
    }

    fun query(start: Int, endExclusive: Int): Seg {
        var l = maxOf(start, 0) + tsize
        var r = minOf(endExclusive, size) + tsize

        push(l)
        push(r-1)

        var lacc = identityValue
        var racc = identityValue

        while(l < r) {
            if(l and 1 == 1) {
                lacc = op(lacc, A[l++])
            }
            if(r and 1 == 1) {
                racc = op(A[--r], racc)
            }

            l = l shr 1
            r = r shr 1
        }

        return op(lacc, racc)
    }

    val root get() = A[1]
}

fun Int.bitConcat(other: Int) = toLong().shl(32) or other.toLong().and(0xffff_ffff)

inline class Seg(val data: Long) {
    val best0 get() = (data shr 32).toInt()
    val best1 get() = data.toInt()
    inline operator fun component1() = best0
    inline operator fun component2() = best1

    override fun toString() = "($best0, $best1)"
}
fun Seg(x: Int, y: Int) = Seg(x.bitConcat(y))

inline class SegArray(val longArray: LongArray): Collection<Seg> {
    inline operator fun get(i: Int) = Seg(longArray[i])
    inline operator fun set(i: Int, v: Seg) { longArray[i] = v.data }

    override inline val size: Int get() = longArray.size
    inline val lastIndex get() = longArray.lastIndex
    inline val indices get() = longArray.indices

    override inline fun contains(element: Seg): Boolean = element.data in longArray

    override fun containsAll(elements: Collection<Seg>): Boolean = elements.all(::contains)

    override inline fun isEmpty(): Boolean = longArray.isEmpty()

    override fun iterator(): Iterator<Seg> = object: Iterator<Seg> {
        var index = 0
        override fun hasNext(): Boolean = index < size
        override fun next(): Seg = get(index++)
    }

    fun copyOf(newSize: Int) = SegArray(longArray.copyOf(newSize))
    fun copyOf() = copyOf(size)
}
fun SegArray.copyInto(destination: SegArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) =
    SegArray(longArray.copyInto(destination.longArray, destinationOffset, startIndex, endIndex))
inline fun SegArray(size: Int) = SegArray(LongArray(size))
inline fun SegArray(size: Int, init: (Int) -> Seg) = SegArray(LongArray(size) { init(it).data })

inline fun SegArray.first() = get(0)
inline fun SegArray.last() = get(lastIndex)
inline fun <R> SegArray.fold(init: R, op: (acc: R, Seg) -> R) = longArray.fold(init) { acc, i -> op(acc, Seg(i)) }
inline fun <R> SegArray.foldRight(init: R, op: (Seg, acc: R) -> R) = longArray.foldRight(init) { i, acc -> op(
    Seg(i), acc) }

class IntList(initialCapacity: Int = 12) {
    private var arr = IntArray(initialCapacity)
    val _arr get() = arr
    private val capacity get() = arr.size
    var size = 0
        private set
    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size

    constructor(copyFrom: IntArray): this(copyFrom.size) { copyFrom.copyInto(arr); size = copyFrom.size }
    constructor(copyFrom: Collection<Int>): this(copyFrom.size) { arr = copyFrom.toIntArray(); size = copyFrom.size }

    fun contentEquals(other: IntList): Boolean {
        return this === other || size == other.size && indices.all { this[it] == other[it] }
    }

    private fun grow(minCapacity: Int = 8) {
        val newCapacity = maxOf(minCapacity, capacity + (capacity shr 1))
        arr = arr.copyOf(newCapacity)
    }

    fun ensureCapacity(minCapacity: Int) { if(capacity < minCapacity) grow(minCapacity) }

    operator fun get(index: Int): Int {
        require(index in 0 until size)
        return arr[index]
    }

    operator fun set(index: Int, value: Int) {
        require(index in 0 until size)
        arr[index] = value
    }

    fun add(value: Int) {
        if(size == capacity) grow()
        arr[size++] = value
    }

    fun addAll(list: IntList) {
        ensureCapacity(size + list.size)
        list.arr.copyInto(arr, size, 0, list.size)
        size += list.size
    }

    fun add(index: Int, element: Int) {
        if(size == capacity) grow()
        arr.copyInto(arr, index + 1, index, size)
        size++
        set(index, element)
    }

    fun clear() { size = 0 }

    fun removeAt(index: Int): Int {
        val e = get(index)
        arr.copyInto(arr, index, index + 1, size)
        size--
        return e
    }

    fun indexOf(e: Int): Int {
        for(i in 0 until size) if(this[i] == e) return i
        return -1
    }

    fun remove(e: Int): Boolean {
        val i = indexOf(e)
        if(i == -1) return false
        removeAt(i)
        return true
    }

    operator fun iterator() = object: IntIterator() {
        private var pos = 0
        override fun hasNext() = pos < size
        override fun nextInt() = get(pos++)
    }

    inline fun isEmpty() = size == 0
    inline fun isNotEmpty() = size != 0

    fun pop() = arr[--size]

    fun popToSize(s: Int) {
        require(s >= 0)
        if(s < size) size = s
    }

    fun swap(i: Int, j: Int) { val t = this[i]; this[i] = this[j]; this[j] = t }
    fun reverse() {
        for(i in 0 until size / 2) swap(i, lastIndex - i)
    }

    fun shuffle(rnd: Random = random) { for(i in lastIndex downTo 1) swap(i, rnd.nextInt(i+1)) }

    inline fun sortWith(cmp: (Int, Int) -> Int) { _mergeSort(_arr, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
    inline fun <T: Comparable<T>> sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
    inline fun <T: Comparable<T>> sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
    fun sort() { sortBy { it } }
    fun sortDescending() { sortByDescending { it } }

    fun joinToString(separator: CharSequence) = if(size == 0) "" else let {
        buildString {
            append(it[0])
            for (i in 1 until size) {
                append(separator).append(it[i])
            }
        }
    }

    override fun toString() = "[" + joinToString(", ") + "]"

    fun toIntArray() = arr.copyOf(size)
    fun toList() = List(size, ::get)

    inline fun first() = get(0)
    inline fun last() = get(lastIndex)
}

inline fun IntList(size: Int, init: (Int) -> Int) = IntList(size).apply {
    for(i in 0 until size) { add(init(i)) }
}
inline fun IntArray.toIntList() = IntList(this)
inline fun Collection<Int>.toIntList() = IntList(this)
inline fun intListOf(vararg values: Int) = IntList(values)

fun IntList.max() = (1 until size).fold(this[0]) { acc, i -> max(acc, this[i]) }
fun IntList.min() = (1 until size).fold(this[0]) { acc, i -> min(acc, this[i]) }
fun IntList.getOrNull(i: Int) = if(i in indices) get(i) else null
inline fun IntList.count(predicate: (Int) -> Boolean) = indices.count { predicate(this[it]) }
fun IntList.copyOf() = IntList(size, ::get)

/** IO */
//@JvmField val ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null
//const val PATH = "src/main/resources/"
//@JvmField val INPUT = File(PATH + "input.txt").inputStream()
//@JvmField val OUTPUT = File(PATH + "output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar() else c
    }
}

/** @param skipNext Whether to skip the next character (usually whitespace), defaults to true */
fun readCharArray(n: Int, skipNext: Boolean = true): CharArray {
    val res = CharArray(n) { readChar() }
    if(skipNext) readChar()
    return res
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(c != '\n' && c != Char.MIN_VALUE) {
            append(c)
            c = readChar()
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/**  sort overrides to avoid quicksort attacks */

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

inline fun <A, T> _mergeSort(a0: A, n: Int, tmp0: A, get: A.(Int) -> T, set: A.(Int, T) -> Unit, cmp: (T, T) -> Int) {
    var a = a0
    var tmp = tmp0
    var len = 1
    while(len < n) {
        var l = 0
        while(true) {
            val m = l + len
            if(m >= n) break
            val r = min(n, m + len)
            var i = l
            var j = m
            for(k in l until r) {
                if(i != m && (j == r || cmp(a.get(i), a.get(j)) <= 0)) {
                    tmp.set(k, a.get(i++))
                } else tmp.set(k, a.get(j++))
            }
            l = r
        }
        for(i in l until n) tmp.set(i, a.get(i))
        val t = a; a = tmp; tmp = t
        len += len
    }
    if(a !== a0) for(i in 0 until n) a0.set(i, tmp0.get(i))
}

inline fun IntArray.sortWith(cmp: (Int, Int) -> Int) { _mergeSort(this, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
inline fun <T: Comparable<T>> IntArray.sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> IntArray.sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun IntArray.sort() { sortBy { it } }
fun IntArray.sortDescending() { sortByDescending { it } }

inline fun LongArray.sortWith(cmp: (Long, Long) -> Int) { _mergeSort(this, size, LongArray(size), LongArray::get, LongArray::set, cmp) }
inline fun <T: Comparable<T>> LongArray.sortBy(func: (Long) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> LongArray.sortByDescending(func: (Long) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun LongArray.sort() { sortBy { it } }
fun LongArray.sortDescending() { sortByDescending { it } }

inline fun DoubleArray.sortWith(cmp: (Double, Double) -> Int) { _mergeSort(this, size, DoubleArray(size), DoubleArray::get, DoubleArray::set, cmp) }
inline fun <T: Comparable<T>> DoubleArray.sortBy(func: (Double) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> DoubleArray.sortByDescending(func: (Double) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun DoubleArray.sort() { sortBy { it } }
fun DoubleArray.sortDescending() { sortByDescending { it } }

inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T : Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T : Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T : Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T : Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

// import preserving junk function
@Suppress("NonAsciiCharacters") fun 雪花飄飄北風嘯嘯天地一片蒼茫() { iprintln(max(1, 2)) }

fun IntArray.sumLong() = sumOf { it.toLong() }

fun IntArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun IntArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun LongArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun LongArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun DoubleArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun DoubleArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> List<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> List<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }

// max/min Kotlin 1.6 -> 1.4 shim
fun IntArray.max() = maxOf { it }
fun IntArray.min() = minOf { it }
fun LongArray.max() = maxOf { it }
fun LongArray.min() = minOf { it }
fun CharArray.max() = maxOf { it }
fun CharArray.min() = minOf { it }
fun <T : Comparable<T>> Iterable<T>.max() = maxOf { it }
fun <T : Comparable<T>> Iterable<T>.min() = minOf { it }
fun <T : Comparable<T>> Sequence<T>.max() = maxOf { it }
fun <T : Comparable<T>> Sequence<T>.min() = minOf { it }


@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")
@file:OptIn(ExperimentalStdlibApi::class)

import java.io.PrintWriter
import kotlin.math.*
import kotlin.random.Random
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
//    val startTime = System.nanoTime()

    val numCases = 1//readInt()
    case@ for(case in 1..numCases) {
        //print("Case #$case: ")

       object {
           val n = readInt()
           val G = Array(n) { IntList() }

           val U = IntArray(n-1)
           val V = IntArray(n-1)
           val T = BooleanArray(n-1) { i ->
               U[i] = readInt()-1
               V[i] = readInt()-1

               G[U[i]].add(V[i])
               G[V[i]].add(U[i])

               readInt() == 1
           }

           fun deps(r: Int): IntArray {
               val dep = IntArray(n) { -1 }
               dep[r] = 0
               val stk = intListOf(r)

               while(stk.isNotEmpty()) {
                   val u = stk.pop()
                   for(v in G[u]) if(dep[v] == -1) {
                       dep[v] = dep[u] + 1
                       stk.add(v)
                   }
               }

               return dep
           }

           inner class EulTree(val r: Int) {
               val dep = IntArray(n) { -1 }
               val tree = PropagatingSegmentTree(n, dep)

               val start = IntArray(n)
               val end = IntArray(n)
               init {
                   dep[r] = 0
                   val stk = intListOf(r)
                   val A = SegArray(n)
                   var i = 0

                   while(stk.isNotEmpty()) {
                       var u = stk.pop()
                       if(u >= 0) {
                           stk.add(u.inv())
                           A[i] = Seg(u, -1)
                           start[u] = i++

                           for(v in G[u]) if(dep[v] == -1) {
                               dep[v] = dep[u] + 1
                               stk.add(v)
                           }
                       } else {
                           u = u.inv()
                           end[u] = i
                       }
                   }

                   tree.build(A)
               }

               fun flip(ei: Int) {
                   val u = if(dep[U[ei]] > dep[V[ei]]) U[ei] else V[ei]
                   tree.update(start[u], end[u], true)
               }

               fun bestDep() = dep[tree.root.best0]
           }

           val e0 = run {
               val d0 = deps(0)
               val i = d0.indexOf(d0.max())

               EulTree(i)
           }

           val e1 = run {
               val d0 = e0.dep
               val i = d0.indexOf(d0.max())

               EulTree(i)
           }

           init {
               for(i in 0 until n-1) {
                   if(T[i]) {
                       e0.flip(i)
                       e1.flip(i)
                   }
               }

               val m = readInt()
               repeat(m) {
                   val i = readInt()-1
                   e0.flip(i)
                   e1.flip(i)

                   val ans = max(e0.bestDep(), e1.bestDep())
                   println(ans)
               }
           }

       }
    }

//    iprintln("Time: ${(System.nanoTime() - startTime) / 1000000} ms")
}

class PropagatingSegmentTree(
    val size: Int,
    val dep: IntArray
//    val identityValue: T,
//    val op: (T, T) -> T,
//    val updateIdentity: U,
//    val composer: (U, U) -> U,
//    val updater: (T, U) -> T
) {

    fun best(u: Int, v: Int) = when {
        u == -1 -> v
        v == -1 -> u
        dep[u] > dep[v] -> u
        else -> v
    }

    inline val identityValue: Seg get() = Seg(-1, -1)
    inline fun op(a: Seg, b: Seg): Seg = Seg(best(a.best0, b.best0), best(a.best1, b.best1))
    inline val updateIdentity: Boolean get() = false
    inline fun composer(a: Boolean, b: Boolean): Boolean = a xor b
    inline fun updater(t: Seg, u: Boolean): Seg = if(!u) t else Seg(t.best1, t.best0)

    private inline fun treeSize() = if(size == 0) 0 else Integer.highestOneBit(size.shl(2) - 1)

    @Suppress("UNCHECKED_CAST")
    private val tree = SegArray(treeSize()) { identityValue }
    @Suppress("UNCHECKED_CAST")
    private val lazy = BooleanArray(tree.size)// { updateIdentity }

    fun build(list: SegArray) {
        if(size == 0) return
        build(list, 1, 0, size-1)
    }

    inline fun build(generator: (Int) -> Seg) { build(SegArray(size) { generator(it) }) }

    private inline fun mid(low: Int, high: Int) = (low + high) shr 1
    private fun build(list: SegArray, node: Int, a: Int, b: Int) {
        if(a == b) {
            tree[node] = list[a]
            return
        }

        build(list, node shl 1, a, mid(a, b))
        build(list, node shl 1 or 1, 1 + mid(a, b), b)
        updateNode(node)
    }

    private inline fun updateNode(i: Int) {
        tree[i] = op(tree[i shl 1], tree[i shl 1 or 1])
    }

    fun update(start: Int, endx: Int, value: Boolean) {
        update(1, 0, size-1, start, endx-1, value)
    }
    fun update(range: IntRange, value: Boolean) {
        update(range.first, range.last + 1, value)
    }

    private inline fun updateLazy(i: Int, u: Boolean) {
        lazy[i] = composer(lazy[i], u)
    }

    private fun propagate(node: Int, a: Int, b: Int) {
        tree[node] = updater(tree[node], lazy[node])
        if(a != b) {
            updateLazy(node shl 1, lazy[node])
            updateLazy(node shl 1 or 1, lazy[node])
        }
        lazy[node] = updateIdentity
    }

    private fun update(node: Int, a: Int, b: Int, i: Int, j: Int, u: Boolean) {
        if(lazy[node] != updateIdentity) {
            propagate(node, a, b)
        }

        if(a > b || a > j || b < i) return

        if(a >= i && b <= j) {
            lazy[node] = u
            propagate(node, a, b)
            return
        }

        update(node shl 1, a, mid(a, b), i, j, u)
        update(node shl 1 or 1, 1 + mid(a, b), b, i, j, u)

        updateNode(node)
    }

    fun query(start: Int, endx: Int) =
        query(1, 0, size-1, start, endx-1)
    fun query(range: IntRange) =
        query(range.first, range.last+1)

    private fun query(node: Int, a: Int, b: Int, i: Int, j: Int): Seg {
        if(a > b || a > j || b < i) return identityValue
        if(lazy[node] != updateIdentity) {
            propagate(node, a, b)
        }

        if(a >= i && b <= j) {
            return tree[node]
        }

        val l = query(node shl 1, a, mid(a, b), i, j)
        val r = query(node shl 1 or 1, 1 + mid(a, b), b, i, j)

        return op(l, r)
    }

    val root get() = tree[1]
}

fun Int.bitConcat(other: Int) = toLong().shl(32) or other.toLong().and(0xffff_ffff)

inline class Seg(val data: Long) {
    val best0 get() = (data shr 32).toInt()
    val best1 get() = data.toInt()
    inline operator fun component1() = best0
    inline operator fun component2() = best1

    override fun toString() = "($best0, $best1)"
}
fun Seg(x: Int, y: Int) = Seg(x.bitConcat(y))

inline class SegArray(val longArray: LongArray): Collection<Seg> {
    inline operator fun get(i: Int) = Seg(longArray[i])
    inline operator fun set(i: Int, v: Seg) { longArray[i] = v.data }

    override inline val size: Int get() = longArray.size
    inline val lastIndex get() = longArray.lastIndex
    inline val indices get() = longArray.indices

    override inline fun contains(element: Seg): Boolean = element.data in longArray

    override fun containsAll(elements: Collection<Seg>): Boolean = elements.all(::contains)

    override inline fun isEmpty(): Boolean = longArray.isEmpty()

    override fun iterator(): Iterator<Seg> = object: Iterator<Seg> {
        var index = 0
        override fun hasNext(): Boolean = index < size
        override fun next(): Seg = get(index++)
    }

    fun copyOf(newSize: Int) = SegArray(longArray.copyOf(newSize))
    fun copyOf() = copyOf(size)
}
fun SegArray.copyInto(destination: SegArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) =
    SegArray(longArray.copyInto(destination.longArray, destinationOffset, startIndex, endIndex))
inline fun SegArray(size: Int) = SegArray(LongArray(size))
inline fun SegArray(size: Int, init: (Int) -> Seg) = SegArray(LongArray(size) { init(it).data })

inline fun SegArray.first() = get(0)
inline fun SegArray.last() = get(lastIndex)
inline fun <R> SegArray.fold(init: R, op: (acc: R, Seg) -> R) = longArray.fold(init) { acc, i -> op(acc, Seg(i)) }
inline fun <R> SegArray.foldRight(init: R, op: (Seg, acc: R) -> R) = longArray.foldRight(init) { i, acc -> op(
    Seg(i), acc) }

class IntList(initialCapacity: Int = 12) {
    private var arr = IntArray(initialCapacity)
    val _arr get() = arr
    private val capacity get() = arr.size
    var size = 0
        private set
    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size

    constructor(copyFrom: IntArray): this(copyFrom.size) { copyFrom.copyInto(arr); size = copyFrom.size }
    constructor(copyFrom: Collection<Int>): this(copyFrom.size) { arr = copyFrom.toIntArray(); size = copyFrom.size }

    fun contentEquals(other: IntList): Boolean {
        return this === other || size == other.size && indices.all { this[it] == other[it] }
    }

    private fun grow(minCapacity: Int = 8) {
        val newCapacity = maxOf(minCapacity, capacity + (capacity shr 1))
        arr = arr.copyOf(newCapacity)
    }

    fun ensureCapacity(minCapacity: Int) { if(capacity < minCapacity) grow(minCapacity) }

    operator fun get(index: Int): Int {
        require(index in 0 until size)
        return arr[index]
    }

    operator fun set(index: Int, value: Int) {
        require(index in 0 until size)
        arr[index] = value
    }

    fun add(value: Int) {
        if(size == capacity) grow()
        arr[size++] = value
    }

    fun addAll(list: IntList) {
        ensureCapacity(size + list.size)
        list.arr.copyInto(arr, size, 0, list.size)
        size += list.size
    }

    fun add(index: Int, element: Int) {
        if(size == capacity) grow()
        arr.copyInto(arr, index + 1, index, size)
        size++
        set(index, element)
    }

    fun clear() { size = 0 }

    fun removeAt(index: Int): Int {
        val e = get(index)
        arr.copyInto(arr, index, index + 1, size)
        size--
        return e
    }

    fun indexOf(e: Int): Int {
        for(i in 0 until size) if(this[i] == e) return i
        return -1
    }

    fun remove(e: Int): Boolean {
        val i = indexOf(e)
        if(i == -1) return false
        removeAt(i)
        return true
    }

    operator fun iterator() = object: IntIterator() {
        private var pos = 0
        override fun hasNext() = pos < size
        override fun nextInt() = get(pos++)
    }

    inline fun isEmpty() = size == 0
    inline fun isNotEmpty() = size != 0

    fun pop() = arr[--size]

    fun popToSize(s: Int) {
        require(s >= 0)
        if(s < size) size = s
    }

    fun swap(i: Int, j: Int) { val t = this[i]; this[i] = this[j]; this[j] = t }
    fun reverse() {
        for(i in 0 until size / 2) swap(i, lastIndex - i)
    }

    fun shuffle(rnd: Random = random) { for(i in lastIndex downTo 1) swap(i, rnd.nextInt(i+1)) }

    inline fun sortWith(cmp: (Int, Int) -> Int) { _mergeSort(_arr, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
    inline fun <T: Comparable<T>> sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
    inline fun <T: Comparable<T>> sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
    fun sort() { sortBy { it } }
    fun sortDescending() { sortByDescending { it } }

    fun joinToString(separator: CharSequence) = if(size == 0) "" else let {
        buildString {
            append(it[0])
            for (i in 1 until size) {
                append(separator).append(it[i])
            }
        }
    }

    override fun toString() = "[" + joinToString(", ") + "]"

    fun toIntArray() = arr.copyOf(size)
    fun toList() = List(size, ::get)

    inline fun first() = get(0)
    inline fun last() = get(lastIndex)
}

inline fun IntList(size: Int, init: (Int) -> Int) = IntList(size).apply {
    for(i in 0 until size) { add(init(i)) }
}
inline fun IntArray.toIntList() = IntList(this)
inline fun Collection<Int>.toIntList() = IntList(this)
inline fun intListOf(vararg values: Int) = IntList(values)

fun IntList.max() = (1 until size).fold(this[0]) { acc, i -> max(acc, this[i]) }
fun IntList.min() = (1 until size).fold(this[0]) { acc, i -> min(acc, this[i]) }
fun IntList.getOrNull(i: Int) = if(i in indices) get(i) else null
inline fun IntList.count(predicate: (Int) -> Boolean) = indices.count { predicate(this[it]) }
fun IntList.copyOf() = IntList(size, ::get)

/** IO */
//@JvmField val ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null
//const val PATH = "src/main/resources/"
//@JvmField val INPUT = File(PATH + "input.txt").inputStream()
//@JvmField val OUTPUT = File(PATH + "output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar() else c
    }
}

/** @param skipNext Whether to skip the next character (usually whitespace), defaults to true */
fun readCharArray(n: Int, skipNext: Boolean = true): CharArray {
    val res = CharArray(n) { readChar() }
    if(skipNext) readChar()
    return res
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(c != '\n' && c != Char.MIN_VALUE) {
            append(c)
            c = readChar()
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/**  sort overrides to avoid quicksort attacks */

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

inline fun <A, T> _mergeSort(a0: A, n: Int, tmp0: A, get: A.(Int) -> T, set: A.(Int, T) -> Unit, cmp: (T, T) -> Int) {
    var a = a0
    var tmp = tmp0
    var len = 1
    while(len < n) {
        var l = 0
        while(true) {
            val m = l + len
            if(m >= n) break
            val r = min(n, m + len)
            var i = l
            var j = m
            for(k in l until r) {
                if(i != m && (j == r || cmp(a.get(i), a.get(j)) <= 0)) {
                    tmp.set(k, a.get(i++))
                } else tmp.set(k, a.get(j++))
            }
            l = r
        }
        for(i in l until n) tmp.set(i, a.get(i))
        val t = a; a = tmp; tmp = t
        len += len
    }
    if(a !== a0) for(i in 0 until n) a0.set(i, tmp0.get(i))
}

inline fun IntArray.sortWith(cmp: (Int, Int) -> Int) { _mergeSort(this, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
inline fun <T: Comparable<T>> IntArray.sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> IntArray.sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun IntArray.sort() { sortBy { it } }
fun IntArray.sortDescending() { sortByDescending { it } }

inline fun LongArray.sortWith(cmp: (Long, Long) -> Int) { _mergeSort(this, size, LongArray(size), LongArray::get, LongArray::set, cmp) }
inline fun <T: Comparable<T>> LongArray.sortBy(func: (Long) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> LongArray.sortByDescending(func: (Long) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun LongArray.sort() { sortBy { it } }
fun LongArray.sortDescending() { sortByDescending { it } }

inline fun DoubleArray.sortWith(cmp: (Double, Double) -> Int) { _mergeSort(this, size, DoubleArray(size), DoubleArray::get, DoubleArray::set, cmp) }
inline fun <T: Comparable<T>> DoubleArray.sortBy(func: (Double) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> DoubleArray.sortByDescending(func: (Double) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun DoubleArray.sort() { sortBy { it } }
fun DoubleArray.sortDescending() { sortByDescending { it } }

inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T : Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T : Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T : Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T : Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

// import preserving junk function
@Suppress("NonAsciiCharacters") fun 雪花飄飄北風嘯嘯天地一片蒼茫() { iprintln(max(1, 2)) }

fun IntArray.sumLong() = sumOf { it.toLong() }

fun IntArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun IntArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun LongArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun LongArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun DoubleArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun DoubleArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> List<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> List<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }

// max/min Kotlin 1.6 -> 1.4 shim
fun IntArray.max() = maxOf { it }
fun IntArray.min() = minOf { it }
fun LongArray.max() = maxOf { it }
fun LongArray.min() = minOf { it }
fun CharArray.max() = maxOf { it }
fun CharArray.min() = minOf { it }
fun <T : Comparable<T>> Iterable<T>.max() = maxOf { it }
fun <T : Comparable<T>> Iterable<T>.min() = minOf { it }
fun <T : Comparable<T>> Sequence<T>.max() = maxOf { it }
fun <T : Comparable<T>> Sequence<T>.min() = minOf { it }


@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")
@file:OptIn(ExperimentalStdlibApi::class)

import java.io.PrintWriter
import kotlin.math.*
import kotlin.random.Random
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
//    val startTime = System.nanoTime()

    val numCases = 1//readInt()
    case@ for(case in 1..numCases) {
        //print("Case #$case: ")

        object {
            val n = readInt()
            val G = Array(n) { IntList() }

            val U = IntArray(n-1)
            val V = IntArray(n-1)
            val T = BooleanArray(n-1) { i ->
                U[i] = readInt()-1
                V[i] = readInt()-1

                G[U[i]].add(V[i])
                G[V[i]].add(U[i])

                readInt() == 1
            }

            fun deps(r: Int): IntArray {
                val dep = IntArray(n) { -1 }
                dep[r] = 0
                val stk = intListOf(r)

                while(stk.isNotEmpty()) {
                    val u = stk.pop()
                    for(v in G[u]) if(dep[v] == -1) {
                        dep[v] = dep[u] + 1
                        stk.add(v)
                    }
                }

                return dep
            }

            inner class EulTree(val r: Int) {
                val dep = IntArray(n) { -1 }
                val tree = PropagatingSegmentTree(n, dep)

                val start = IntArray(n)
                val end = IntArray(n)
                init {
                    dep[r] = 0
                    val stk = intListOf(r)
                    val A = SegArray(n)
                    var i = 0

                    while(stk.isNotEmpty()) {
                        var u = stk.pop()
                        if(u >= 0) {
                            stk.add(u.inv())
                            A[i] = Seg(u, -1)
                            start[u] = i++

                            for(v in G[u]) if(dep[v] == -1) {
                                dep[v] = dep[u] + 1
                                stk.add(v)
                            }
                        } else {
                            u = u.inv()
                            end[u] = i
                        }
                    }

                    tree.build(A)
                }

                fun flip(ei: Int) {
                    val u = if(dep[U[ei]] > dep[V[ei]]) U[ei] else V[ei]
                    tree.update(start[u], end[u], true)
                }

                fun bestDep() = dep[tree.root.best0]
            }

            val e0 = run {
                val d0 = deps(0)
                val i = d0.indexOf(d0.max())

                EulTree(i)
            }

            val e1 = run {
                val d0 = e0.dep
                val i = d0.indexOf(d0.max())

                EulTree(i)
            }

            init {
                for(i in 0 until n-1) {
                    if(T[i]) {
                        e0.flip(i)
                        e1.flip(i)
                    }
                }

                val m = readInt()
                repeat(m) {
                    val i = readInt()-1
                    e0.flip(i)
                    e1.flip(i)

                    val ans = max(e0.bestDep(), e1.bestDep())
                    println(ans)
                }
            }

        }
    }

//    iprintln("Time: ${(System.nanoTime() - startTime) / 1000000} ms")
}

class PropagatingSegmentTree(
    val size: Int,
    val dep: IntArray
//    val identityValue: T,
//    val op: (T, T) -> T,
//    val updateIdentity: U,
//    val composer: (U, U) -> U,
//    val updater: (T, U) -> T
) {

    fun best(u: Int, v: Int) = when {
        u == -1 -> v
        v == -1 -> u
        dep[u] > dep[v] -> u
        else -> v
    }

    inline val identityValue: Seg get() = Seg(-1, -1)
    inline fun op(a: Seg, b: Seg): Seg = Seg(best(a.best0, b.best0), best(a.best1, b.best1))
    inline val updateIdentity: Boolean get() = false
    inline fun composer(a: Boolean, b: Boolean): Boolean = a xor b
    inline fun updater(t: Seg, u: Boolean): Seg = if(!u) t else Seg(t.best1, t.best0)

    private inline fun treeSize() = if(size == 0) 0 else Integer.highestOneBit(size.shl(2) - 1)

    @Suppress("UNCHECKED_CAST")
    private val tree = SegArray(treeSize()) { identityValue }
    @Suppress("UNCHECKED_CAST")
    private val lazy = BooleanArray(tree.size)// { updateIdentity }

    fun build(list: SegArray) {
        if(size == 0) return
        build(list, 1, 0, size-1)
    }

    inline fun build(generator: (Int) -> Seg) { build(SegArray(size) { generator(it) }) }

    private inline fun mid(low: Int, high: Int) = (low + high) shr 1
    private fun build(list: SegArray, node: Int, a: Int, b: Int) {
        if(a == b) {
            tree[node] = list[a]
            return
        }

        build(list, node shl 1, a, mid(a, b))
        build(list, node shl 1 or 1, 1 + mid(a, b), b)
        updateNode(node)
    }

    private inline fun updateNode(i: Int) {
        tree[i] = op(tree[i shl 1], tree[i shl 1 or 1])
    }

    fun update(start: Int, endx: Int, value: Boolean) {
        update(1, 0, size-1, start, endx-1, value)
    }
    fun update(range: IntRange, value: Boolean) {
        update(range.first, range.last + 1, value)
    }

    private inline fun updateLazy(i: Int, u: Boolean) {
        lazy[i] = composer(lazy[i], u)
    }

    private fun propagate(node: Int, a: Int, b: Int) {
        tree[node] = updater(tree[node], lazy[node])
        if(a != b) {
            updateLazy(node shl 1, lazy[node])
            updateLazy(node shl 1 or 1, lazy[node])
        }
        lazy[node] = updateIdentity
    }

    private fun update(node: Int, a: Int, b: Int, i: Int, j: Int, u: Boolean) {
        if(lazy[node] != updateIdentity) {
            propagate(node, a, b)
        }

        if(a > b || a > j || b < i) return

        if(a >= i && b <= j) {
            lazy[node] = u
            propagate(node, a, b)
            return
        }

        update(node shl 1, a, mid(a, b), i, j, u)
        update(node shl 1 or 1, 1 + mid(a, b), b, i, j, u)

        updateNode(node)
    }

    fun query(start: Int, endx: Int) =
        query(1, 0, size-1, start, endx-1)
    fun query(range: IntRange) =
        query(range.first, range.last+1)

    private fun query(node: Int, a: Int, b: Int, i: Int, j: Int): Seg {
        if(a > b || a > j || b < i) return identityValue
        if(lazy[node] != updateIdentity) {
            propagate(node, a, b)
        }

        if(a >= i && b <= j) {
            return tree[node]
        }

        val l = query(node shl 1, a, mid(a, b), i, j)
        val r = query(node shl 1 or 1, 1 + mid(a, b), b, i, j)

        return op(l, r)
    }

    val root get() = tree[1]
}

fun Int.bitConcat(other: Int) = toLong().shl(32) or other.toLong().and(0xffff_ffff)

inline class Seg(val data: Long) {
    val best0 get() = (data shr 32).toInt()
    val best1 get() = data.toInt()
    inline operator fun component1() = best0
    inline operator fun component2() = best1

    override fun toString() = "($best0, $best1)"
}
fun Seg(x: Int, y: Int) = Seg(x.bitConcat(y))

inline class SegArray(val longArray: LongArray): Collection<Seg> {
    inline operator fun get(i: Int) = Seg(longArray[i])
    inline operator fun set(i: Int, v: Seg) { longArray[i] = v.data }

    override inline val size: Int get() = longArray.size
    inline val lastIndex get() = longArray.lastIndex
    inline val indices get() = longArray.indices

    override inline fun contains(element: Seg): Boolean = element.data in longArray

    override fun containsAll(elements: Collection<Seg>): Boolean = elements.all(::contains)

    override inline fun isEmpty(): Boolean = longArray.isEmpty()

    override fun iterator(): Iterator<Seg> = object: Iterator<Seg> {
        var index = 0
        override fun hasNext(): Boolean = index < size
        override fun next(): Seg = get(index++)
    }

    fun copyOf(newSize: Int) = SegArray(longArray.copyOf(newSize))
    fun copyOf() = copyOf(size)
}
fun SegArray.copyInto(destination: SegArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) =
    SegArray(longArray.copyInto(destination.longArray, destinationOffset, startIndex, endIndex))
inline fun SegArray(size: Int) = SegArray(LongArray(size))
inline fun SegArray(size: Int, init: (Int) -> Seg) = SegArray(LongArray(size) { init(it).data })

inline fun SegArray.first() = get(0)
inline fun SegArray.last() = get(lastIndex)
inline fun <R> SegArray.fold(init: R, op: (acc: R, Seg) -> R) = longArray.fold(init) { acc, i -> op(acc, Seg(i)) }
inline fun <R> SegArray.foldRight(init: R, op: (Seg, acc: R) -> R) = longArray.foldRight(init) { i, acc -> op(
    Seg(i), acc) }

class IntList(initialCapacity: Int = 12) {
    private var arr = IntArray(initialCapacity)
    val _arr get() = arr
    private val capacity get() = arr.size
    var size = 0
        private set
    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size

    constructor(copyFrom: IntArray): this(copyFrom.size) { copyFrom.copyInto(arr); size = copyFrom.size }
    constructor(copyFrom: Collection<Int>): this(copyFrom.size) { arr = copyFrom.toIntArray(); size = copyFrom.size }

    fun contentEquals(other: IntList): Boolean {
        return this === other || size == other.size && indices.all { this[it] == other[it] }
    }

    private fun grow(minCapacity: Int = 8) {
        val newCapacity = maxOf(minCapacity, capacity + (capacity shr 1))
        arr = arr.copyOf(newCapacity)
    }

    fun ensureCapacity(minCapacity: Int) { if(capacity < minCapacity) grow(minCapacity) }

    operator fun get(index: Int): Int {
        require(index in 0 until size)
        return arr[index]
    }

    operator fun set(index: Int, value: Int) {
        require(index in 0 until size)
        arr[index] = value
    }

    fun add(value: Int) {
        if(size == capacity) grow()
        arr[size++] = value
    }

    fun addAll(list: IntList) {
        ensureCapacity(size + list.size)
        list.arr.copyInto(arr, size, 0, list.size)
        size += list.size
    }

    fun add(index: Int, element: Int) {
        if(size == capacity) grow()
        arr.copyInto(arr, index + 1, index, size)
        size++
        set(index, element)
    }

    fun clear() { size = 0 }

    fun removeAt(index: Int): Int {
        val e = get(index)
        arr.copyInto(arr, index, index + 1, size)
        size--
        return e
    }

    fun indexOf(e: Int): Int {
        for(i in 0 until size) if(this[i] == e) return i
        return -1
    }

    fun remove(e: Int): Boolean {
        val i = indexOf(e)
        if(i == -1) return false
        removeAt(i)
        return true
    }

    operator fun iterator() = object: IntIterator() {
        private var pos = 0
        override fun hasNext() = pos < size
        override fun nextInt() = get(pos++)
    }

    inline fun isEmpty() = size == 0
    inline fun isNotEmpty() = size != 0

    fun pop() = arr[--size]

    fun popToSize(s: Int) {
        require(s >= 0)
        if(s < size) size = s
    }

    fun swap(i: Int, j: Int) { val t = this[i]; this[i] = this[j]; this[j] = t }
    fun reverse() {
        for(i in 0 until size / 2) swap(i, lastIndex - i)
    }

    fun shuffle(rnd: Random = random) { for(i in lastIndex downTo 1) swap(i, rnd.nextInt(i+1)) }

    inline fun sortWith(cmp: (Int, Int) -> Int) { _mergeSort(_arr, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
    inline fun <T: Comparable<T>> sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
    inline fun <T: Comparable<T>> sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
    fun sort() { sortBy { it } }
    fun sortDescending() { sortByDescending { it } }

    fun joinToString(separator: CharSequence) = if(size == 0) "" else let {
        buildString {
            append(it[0])
            for (i in 1 until size) {
                append(separator).append(it[i])
            }
        }
    }

    override fun toString() = "[" + joinToString(", ") + "]"

    fun toIntArray() = arr.copyOf(size)
    fun toList() = List(size, ::get)

    inline fun first() = get(0)
    inline fun last() = get(lastIndex)
}

inline fun IntList(size: Int, init: (Int) -> Int) = IntList(size).apply {
    for(i in 0 until size) { add(init(i)) }
}
inline fun IntArray.toIntList() = IntList(this)
inline fun Collection<Int>.toIntList() = IntList(this)
inline fun intListOf(vararg values: Int) = IntList(values)

fun IntList.max() = (1 until size).fold(this[0]) { acc, i -> max(acc, this[i]) }
fun IntList.min() = (1 until size).fold(this[0]) { acc, i -> min(acc, this[i]) }
fun IntList.getOrNull(i: Int) = if(i in indices) get(i) else null
inline fun IntList.count(predicate: (Int) -> Boolean) = indices.count { predicate(this[it]) }
fun IntList.copyOf() = IntList(size, ::get)

/** IO */
//@JvmField val ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null
//const val PATH = "src/main/resources/"
//@JvmField val INPUT = File(PATH + "input.txt").inputStream()
//@JvmField val OUTPUT = File(PATH + "output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar() else c
    }
}

/** @param skipNext Whether to skip the next character (usually whitespace), defaults to true */
fun readCharArray(n: Int, skipNext: Boolean = true): CharArray {
    val res = CharArray(n) { readChar() }
    if(skipNext) readChar()
    return res
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(c != '\n' && c != Char.MIN_VALUE) {
            append(c)
            c = readChar()
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt(): Int {
    var ret = 0
    var c = readChar()
    while(c <= ' ') c = readChar()
    val neg = c == '-'
    if(neg) c = readChar()
    do {
        ret = ret * 10 + (c - '0')
        c = readChar()
    } while (c in '0'..'9')

    return if(neg) -ret else ret
}
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/**  sort overrides to avoid quicksort attacks */

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

inline fun <A, T> _mergeSort(a0: A, n: Int, tmp0: A, get: A.(Int) -> T, set: A.(Int, T) -> Unit, cmp: (T, T) -> Int) {
    var a = a0
    var tmp = tmp0
    var len = 1
    while(len < n) {
        var l = 0
        while(true) {
            val m = l + len
            if(m >= n) break
            val r = min(n, m + len)
            var i = l
            var j = m
            for(k in l until r) {
                if(i != m && (j == r || cmp(a.get(i), a.get(j)) <= 0)) {
                    tmp.set(k, a.get(i++))
                } else tmp.set(k, a.get(j++))
            }
            l = r
        }
        for(i in l until n) tmp.set(i, a.get(i))
        val t = a; a = tmp; tmp = t
        len += len
    }
    if(a !== a0) for(i in 0 until n) a0.set(i, tmp0.get(i))
}

inline fun IntArray.sortWith(cmp: (Int, Int) -> Int) { _mergeSort(this, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
inline fun <T: Comparable<T>> IntArray.sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> IntArray.sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun IntArray.sort() { sortBy { it } }
fun IntArray.sortDescending() { sortByDescending { it } }

inline fun LongArray.sortWith(cmp: (Long, Long) -> Int) { _mergeSort(this, size, LongArray(size), LongArray::get, LongArray::set, cmp) }
inline fun <T: Comparable<T>> LongArray.sortBy(func: (Long) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> LongArray.sortByDescending(func: (Long) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun LongArray.sort() { sortBy { it } }
fun LongArray.sortDescending() { sortByDescending { it } }

inline fun DoubleArray.sortWith(cmp: (Double, Double) -> Int) { _mergeSort(this, size, DoubleArray(size), DoubleArray::get, DoubleArray::set, cmp) }
inline fun <T: Comparable<T>> DoubleArray.sortBy(func: (Double) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> DoubleArray.sortByDescending(func: (Double) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun DoubleArray.sort() { sortBy { it } }
fun DoubleArray.sortDescending() { sortByDescending { it } }

inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T : Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T : Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T : Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T : Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

// import preserving junk function
@Suppress("NonAsciiCharacters") fun 雪花飄飄北風嘯嘯天地一片蒼茫() { iprintln(max(1, 2)) }

fun IntArray.sumLong() = sumOf { it.toLong() }

fun IntArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun IntArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun LongArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun LongArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun DoubleArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun DoubleArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> List<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> List<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }

// max/min Kotlin 1.6 -> 1.4 shim
fun IntArray.max() = maxOf { it }
fun IntArray.min() = minOf { it }
fun LongArray.max() = maxOf { it }
fun LongArray.min() = minOf { it }
fun CharArray.max() = maxOf { it }
fun CharArray.min() = minOf { it }
fun <T : Comparable<T>> Iterable<T>.max() = maxOf { it }
fun <T : Comparable<T>> Iterable<T>.min() = minOf { it }
fun <T : Comparable<T>> Sequence<T>.max() = maxOf { it }
fun <T : Comparable<T>> Sequence<T>.min() = minOf { it }


@file:Suppress("NOTHING_TO_INLINE", "EXPERIMENTAL_FEATURE_WARNING", "OVERRIDE_BY_INLINE")
@file:OptIn(ExperimentalStdlibApi::class)

import java.io.PrintWriter
import kotlin.math.*
import kotlin.random.Random
import kotlin.collections.sort as _sort
import kotlin.collections.sortDescending as _sortDescending
import kotlin.io.println as iprintln

/** @author Spheniscine */
fun main() { _writer.solve(); _writer.flush() }
fun PrintWriter.solve() {
//    val startTime = System.nanoTime()

    val numCases = 1//readInt()
    case@ for(case in 1..numCases) {
        //print("Case #$case: ")

       object {
           val n = readInt()
           val G = Array(n) { IntList() }

           val U = IntArray(n-1)
           val V = IntArray(n-1)
           val T = BooleanArray(n-1) { i ->
               U[i] = readInt()-1
               V[i] = readInt()-1

               G[U[i]].add(V[i])
               G[V[i]].add(U[i])

               readInt() == 1
           }

           fun deps(r: Int): IntArray {
               val dep = IntArray(n) { -1 }
               dep[r] = 0
               val stk = intListOf(r)

               while(stk.isNotEmpty()) {
                   val u = stk.pop()
                   for(v in G[u]) if(dep[v] == -1) {
                       dep[v] = dep[u] + 1
                       stk.add(v)
                   }
               }

               return dep
           }

           inner class EulTree(val r: Int) {
               val dep = deps(r)
               val tree = PropagatingSegmentTree(n, dep)

               val start = IntArray(n)
               val end = IntArray(n)
               init {
                   val stk = intListOf(r)
                   val A = SegArray(n)
                   var i = 0

                   while(stk.isNotEmpty()) {
                       var u = stk.pop()
                       if(u >= 0) {
                           stk.add(u.inv())
                           A[i] = Seg(u, -1)
                           start[u] = i++

                           for(v in G[u]) if(dep[v] > dep[u]) {
                               stk.add(v)
                           }
                       } else {
                           u = u.inv()
                           end[u] = i
                       }
                   }

                   tree.build(A)
               }

               fun flip(ei: Int) {
                   val u = if(dep[U[ei]] > dep[V[ei]]) U[ei] else V[ei]
                   tree.update(start[u], end[u], true)
               }

               fun bestDep() = dep[tree.root.best0]
           }

           val e0 = run {
               val d0 = deps(0)
               val i = d0.indexOf(d0.max())

               EulTree(i)
           }

           val e1 = run {
               val d0 = e0.dep
               val i = d0.indexOf(d0.max())

               EulTree(i)
           }

           init {
               for(i in 0 until n-1) {
                   if(T[i]) {
                       e0.flip(i)
                       e1.flip(i)
                   }
               }

               val m = readInt()
               repeat(m) {
                   val i = readInt()-1
                   e0.flip(i)
                   e1.flip(i)

                   val ans = max(e0.bestDep(), e1.bestDep())
                   println(ans)
               }
           }

       }
    }

//    iprintln("Time: ${(System.nanoTime() - startTime) / 1000000} ms")
}

class PropagatingSegmentTree(
    val size: Int,
    val dep: IntArray
//    val identityValue: T,
//    val op: (T, T) -> T,
//    val updateIdentity: U,
//    val composer: (U, U) -> U,
//    val updater: (T, U) -> T
) {

    fun best(u: Int, v: Int) = when {
        u == -1 -> v
        v == -1 -> u
        dep[u] > dep[v] -> u
        else -> v
    }

    inline val identityValue: Seg get() = Seg(-1, -1)
    inline fun op(a: Seg, b: Seg): Seg = Seg(best(a.best0, b.best0), best(a.best1, b.best1))
    inline val updateIdentity: Boolean get() = false
    inline fun composer(a: Boolean, b: Boolean): Boolean = a xor b
    inline fun updater(t: Seg, u: Boolean): Seg = if(!u) t else Seg(t.best1, t.best0)

    private inline fun treeSize() = if(size == 0) 0 else Integer.highestOneBit(size.shl(2) - 1)

    @Suppress("UNCHECKED_CAST")
    private val tree = SegArray(treeSize()) { identityValue }
    @Suppress("UNCHECKED_CAST")
    private val lazy = BooleanArray(tree.size)// { updateIdentity }

    fun build(list: SegArray) {
        if(size == 0) return
        build(list, 1, 0, size-1)
    }

    inline fun build(generator: (Int) -> Seg) { build(SegArray(size) { generator(it) }) }

    private inline fun mid(low: Int, high: Int) = (low + high) shr 1
    private fun build(list: SegArray, node: Int, a: Int, b: Int) {
        if(a == b) {
            tree[node] = list[a]
            return
        }

        build(list, node shl 1, a, mid(a, b))
        build(list, node shl 1 or 1, 1 + mid(a, b), b)
        updateNode(node)
    }

    private inline fun updateNode(i: Int) {
        tree[i] = op(tree[i shl 1], tree[i shl 1 or 1])
    }

    fun update(start: Int, endx: Int, value: Boolean) {
        update(1, 0, size-1, start, endx-1, value)
    }
    fun update(range: IntRange, value: Boolean) {
        update(range.first, range.last + 1, value)
    }

    private inline fun updateLazy(i: Int, u: Boolean) {
        lazy[i] = composer(lazy[i], u)
    }

    private fun propagate(node: Int, a: Int, b: Int) {
        tree[node] = updater(tree[node], lazy[node])
        if(a != b) {
            updateLazy(node shl 1, lazy[node])
            updateLazy(node shl 1 or 1, lazy[node])
        }
        lazy[node] = updateIdentity
    }

    private fun update(node: Int, a: Int, b: Int, i: Int, j: Int, u: Boolean) {
        if(lazy[node] != updateIdentity) {
            propagate(node, a, b)
        }

        if(a > b || a > j || b < i) return

        if(a >= i && b <= j) {
            lazy[node] = u
            propagate(node, a, b)
            return
        }

        update(node shl 1, a, mid(a, b), i, j, u)
        update(node shl 1 or 1, 1 + mid(a, b), b, i, j, u)

        updateNode(node)
    }

    fun query(start: Int, endx: Int) =
        query(1, 0, size-1, start, endx-1)
    fun query(range: IntRange) =
        query(range.first, range.last+1)

    private fun query(node: Int, a: Int, b: Int, i: Int, j: Int): Seg {
        if(a > b || a > j || b < i) return identityValue
        if(lazy[node] != updateIdentity) {
            propagate(node, a, b)
        }

        if(a >= i && b <= j) {
            return tree[node]
        }

        val l = query(node shl 1, a, mid(a, b), i, j)
        val r = query(node shl 1 or 1, 1 + mid(a, b), b, i, j)

        return op(l, r)
    }

    val root get() = tree[1]
}

fun Int.bitConcat(other: Int) = toLong().shl(32) or other.toLong().and(0xffff_ffff)

inline class Seg(val data: Long) {
    val best0 get() = (data shr 32).toInt()
    val best1 get() = data.toInt()
    inline operator fun component1() = best0
    inline operator fun component2() = best1

    override fun toString() = "($best0, $best1)"
}
fun Seg(x: Int, y: Int) = Seg(x.bitConcat(y))

inline class SegArray(val longArray: LongArray): Collection<Seg> {
    inline operator fun get(i: Int) = Seg(longArray[i])
    inline operator fun set(i: Int, v: Seg) { longArray[i] = v.data }

    override inline val size: Int get() = longArray.size
    inline val lastIndex get() = longArray.lastIndex
    inline val indices get() = longArray.indices

    override inline fun contains(element: Seg): Boolean = element.data in longArray

    override fun containsAll(elements: Collection<Seg>): Boolean = elements.all(::contains)

    override inline fun isEmpty(): Boolean = longArray.isEmpty()

    override fun iterator(): Iterator<Seg> = object: Iterator<Seg> {
        var index = 0
        override fun hasNext(): Boolean = index < size
        override fun next(): Seg = get(index++)
    }

    fun copyOf(newSize: Int) = SegArray(longArray.copyOf(newSize))
    fun copyOf() = copyOf(size)
}
fun SegArray.copyInto(destination: SegArray, destinationOffset: Int = 0, startIndex: Int = 0, endIndex: Int = size) =
    SegArray(longArray.copyInto(destination.longArray, destinationOffset, startIndex, endIndex))
inline fun SegArray(size: Int) = SegArray(LongArray(size))
inline fun SegArray(size: Int, init: (Int) -> Seg) = SegArray(LongArray(size) { init(it).data })

inline fun SegArray.first() = get(0)
inline fun SegArray.last() = get(lastIndex)
inline fun <R> SegArray.fold(init: R, op: (acc: R, Seg) -> R) = longArray.fold(init) { acc, i -> op(acc, Seg(i)) }
inline fun <R> SegArray.foldRight(init: R, op: (Seg, acc: R) -> R) = longArray.foldRight(init) { i, acc -> op(
    Seg(i), acc) }

class IntList(initialCapacity: Int = 12) {
    private var arr = IntArray(initialCapacity)
    val _arr get() = arr
    private val capacity get() = arr.size
    var size = 0
        private set
    inline val lastIndex get() = size - 1
    inline val indices get() = 0 until size

    constructor(copyFrom: IntArray): this(copyFrom.size) { copyFrom.copyInto(arr); size = copyFrom.size }
    constructor(copyFrom: Collection<Int>): this(copyFrom.size) { arr = copyFrom.toIntArray(); size = copyFrom.size }

    fun contentEquals(other: IntList): Boolean {
        return this === other || size == other.size && indices.all { this[it] == other[it] }
    }

    private fun grow(minCapacity: Int = 8) {
        val newCapacity = maxOf(minCapacity, capacity + (capacity shr 1))
        arr = arr.copyOf(newCapacity)
    }

    fun ensureCapacity(minCapacity: Int) { if(capacity < minCapacity) grow(minCapacity) }

    operator fun get(index: Int): Int {
        require(index in 0 until size)
        return arr[index]
    }

    operator fun set(index: Int, value: Int) {
        require(index in 0 until size)
        arr[index] = value
    }

    fun add(value: Int) {
        if(size == capacity) grow()
        arr[size++] = value
    }

    fun addAll(list: IntList) {
        ensureCapacity(size + list.size)
        list.arr.copyInto(arr, size, 0, list.size)
        size += list.size
    }

    fun add(index: Int, element: Int) {
        if(size == capacity) grow()
        arr.copyInto(arr, index + 1, index, size)
        size++
        set(index, element)
    }

    fun clear() { size = 0 }

    fun removeAt(index: Int): Int {
        val e = get(index)
        arr.copyInto(arr, index, index + 1, size)
        size--
        return e
    }

    fun indexOf(e: Int): Int {
        for(i in 0 until size) if(this[i] == e) return i
        return -1
    }

    fun remove(e: Int): Boolean {
        val i = indexOf(e)
        if(i == -1) return false
        removeAt(i)
        return true
    }

    operator fun iterator() = object: IntIterator() {
        private var pos = 0
        override fun hasNext() = pos < size
        override fun nextInt() = get(pos++)
    }

    inline fun isEmpty() = size == 0
    inline fun isNotEmpty() = size != 0

    fun pop() = arr[--size]

    fun popToSize(s: Int) {
        require(s >= 0)
        if(s < size) size = s
    }

    fun swap(i: Int, j: Int) { val t = this[i]; this[i] = this[j]; this[j] = t }
    fun reverse() {
        for(i in 0 until size / 2) swap(i, lastIndex - i)
    }

    fun shuffle(rnd: Random = random) { for(i in lastIndex downTo 1) swap(i, rnd.nextInt(i+1)) }

    inline fun sortWith(cmp: (Int, Int) -> Int) { _mergeSort(_arr, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
    inline fun <T: Comparable<T>> sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
    inline fun <T: Comparable<T>> sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
    fun sort() { sortBy { it } }
    fun sortDescending() { sortByDescending { it } }

    fun joinToString(separator: CharSequence) = if(size == 0) "" else let {
        buildString {
            append(it[0])
            for (i in 1 until size) {
                append(separator).append(it[i])
            }
        }
    }

    override fun toString() = "[" + joinToString(", ") + "]"

    fun toIntArray() = arr.copyOf(size)
    fun toList() = List(size, ::get)

    inline fun first() = get(0)
    inline fun last() = get(lastIndex)
}

inline fun IntList(size: Int, init: (Int) -> Int) = IntList(size).apply {
    for(i in 0 until size) { add(init(i)) }
}
inline fun IntArray.toIntList() = IntList(this)
inline fun Collection<Int>.toIntList() = IntList(this)
inline fun intListOf(vararg values: Int) = IntList(values)

fun IntList.max() = (1 until size).fold(this[0]) { acc, i -> max(acc, this[i]) }
fun IntList.min() = (1 until size).fold(this[0]) { acc, i -> min(acc, this[i]) }
fun IntList.getOrNull(i: Int) = if(i in indices) get(i) else null
inline fun IntList.count(predicate: (Int) -> Boolean) = indices.count { predicate(this[it]) }
fun IntList.copyOf() = IntList(size, ::get)

/** IO */
//@JvmField val ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null
//const val PATH = "src/main/resources/"
//@JvmField val INPUT = File(PATH + "input.txt").inputStream()
//@JvmField val OUTPUT = File(PATH + "output.txt").outputStream()
@JvmField val INPUT = System.`in`
@JvmField val OUTPUT = System.out

const val _BUFFER_SIZE = 1 shl 16
@JvmField val _buffer = ByteArray(_BUFFER_SIZE)
@JvmField var _bufferPt = 0
@JvmField var _bytesRead = 0

tailrec fun readChar(): Char {
    if(_bufferPt == _bytesRead) {
        _bufferPt = 0
        _bytesRead = INPUT.read(_buffer, 0, _BUFFER_SIZE)
    }
    return if(_bytesRead < 0) Char.MIN_VALUE
    else {
        val c = _buffer[_bufferPt++].toChar()
        if (c == '\r') readChar() else c
    }
}

/** @param skipNext Whether to skip the next character (usually whitespace), defaults to true */
fun readCharArray(n: Int, skipNext: Boolean = true): CharArray {
    val res = CharArray(n) { readChar() }
    if(skipNext) readChar()
    return res
}

fun readLine(): String? {
    var c = readChar()
    return if(c == Char.MIN_VALUE) null
    else buildString {
        while(c != '\n' && c != Char.MIN_VALUE) {
            append(c)
            c = readChar()
        }
    }
}
fun readLn() = readLine()!!

fun read() = buildString {
    var c = readChar()
    while(c <= ' ') {
        if(c == Char.MIN_VALUE) return@buildString
        c = readChar()
    }
    do {
        append(c)
        c = readChar()
    } while(c > ' ')
}
fun readInt() = read().toInt()
fun readDouble() = read().toDouble()
fun readLong() = read().toLong()
fun readStrings(n: Int) = List(n) { read() }
fun readLines(n: Int) = List(n) { readLn() }
fun readInts(n: Int) = List(n) { read().toInt() }
fun readIntArray(n: Int) = IntArray(n) { read().toInt() }
fun readDoubles(n: Int) = List(n) { read().toDouble() }
fun readDoubleArray(n: Int) = DoubleArray(n) { read().toDouble() }
fun readLongs(n: Int) = List(n) { read().toLong() }
fun readLongArray(n: Int) = LongArray(n) { read().toLong() }

@JvmField val _writer = PrintWriter(OUTPUT, false)

/**  sort overrides to avoid quicksort attacks */

@JvmField var _random: Random? = null
val random get() = _random ?: Random(0x594E215C123 * System.nanoTime()).also { _random = it }

inline fun <A, T> _mergeSort(a0: A, n: Int, tmp0: A, get: A.(Int) -> T, set: A.(Int, T) -> Unit, cmp: (T, T) -> Int) {
    var a = a0
    var tmp = tmp0
    var len = 1
    while(len < n) {
        var l = 0
        while(true) {
            val m = l + len
            if(m >= n) break
            val r = min(n, m + len)
            var i = l
            var j = m
            for(k in l until r) {
                if(i != m && (j == r || cmp(a.get(i), a.get(j)) <= 0)) {
                    tmp.set(k, a.get(i++))
                } else tmp.set(k, a.get(j++))
            }
            l = r
        }
        for(i in l until n) tmp.set(i, a.get(i))
        val t = a; a = tmp; tmp = t
        len += len
    }
    if(a !== a0) for(i in 0 until n) a0.set(i, tmp0.get(i))
}

inline fun IntArray.sortWith(cmp: (Int, Int) -> Int) { _mergeSort(this, size, IntArray(size), IntArray::get, IntArray::set, cmp) }
inline fun <T: Comparable<T>> IntArray.sortBy(func: (Int) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> IntArray.sortByDescending(func: (Int) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun IntArray.sort() { sortBy { it } }
fun IntArray.sortDescending() { sortByDescending { it } }

inline fun LongArray.sortWith(cmp: (Long, Long) -> Int) { _mergeSort(this, size, LongArray(size), LongArray::get, LongArray::set, cmp) }
inline fun <T: Comparable<T>> LongArray.sortBy(func: (Long) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> LongArray.sortByDescending(func: (Long) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun LongArray.sort() { sortBy { it } }
fun LongArray.sortDescending() { sortByDescending { it } }

inline fun DoubleArray.sortWith(cmp: (Double, Double) -> Int) { _mergeSort(this, size, DoubleArray(size), DoubleArray::get, DoubleArray::set, cmp) }
inline fun <T: Comparable<T>> DoubleArray.sortBy(func: (Double) -> T) { sortWith { a, b -> func(a).compareTo(func(b)) } }
inline fun <T: Comparable<T>> DoubleArray.sortByDescending(func: (Double) -> T) { sortWith { a, b -> func(b).compareTo(func(a)) } }
fun DoubleArray.sort() { sortBy { it } }
fun DoubleArray.sortDescending() { sortByDescending { it } }

inline fun CharArray.sort() { _sort() }
inline fun CharArray.sortDescending() { _sortDescending() }

inline fun <T : Comparable<T>> Array<out T>.sort() = _sort()
inline fun <T : Comparable<T>> Array<out T>.sortDescending() = _sortDescending()
inline fun <T : Comparable<T>> MutableList<out T>.sort() = _sort()
inline fun <T : Comparable<T>> MutableList<out T>.sortDescending() = _sortDescending()

// import preserving junk function
@Suppress("NonAsciiCharacters") fun 雪花飄飄北風嘯嘯天地一片蒼茫() { iprintln(max(1, 2)) }

fun IntArray.sumLong() = sumOf { it.toLong() }

fun IntArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun IntArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun LongArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun LongArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun DoubleArray.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun DoubleArray.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> Array<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }
fun <T: Comparable<T>> List<T>.sortedIndices() = IntArray(size) { it }.also { it.sortBy(::get) }
fun <T: Comparable<T>> List<T>.sortedIndicesDescending() = IntArray(size) { it }.also { it.sortByDescending(::get) }

// max/min Kotlin 1.6 -> 1.4 shim
fun IntArray.max() = maxOf { it }
fun IntArray.min() = minOf { it }
fun LongArray.max() = maxOf { it }
fun LongArray.min() = minOf { it }
fun CharArray.max() = maxOf { it }
fun CharArray.min() = minOf { it }
fun <T : Comparable<T>> Iterable<T>.max() = maxOf { it }
fun <T : Comparable<T>> Iterable<T>.min() = minOf { it }
fun <T : Comparable<T>> Sequence<T>.max() = maxOf { it }
fun <T : Comparable<T>> Sequence<T>.min() = minOf { it }