In the Land of Fire there are n villages and n-1 bidirectional road, and there is a path between any pair of villages by roads. There are only two types of roads: stone ones and sand ones. Since the Land of Fire is constantly renovating, every morning workers choose a single road and flip its type (so it becomes a stone road if it was a sand road and vice versa). Also everyone here loves ramen, that's why every morning a ramen pavilion is set in the middle of every stone road, and at the end of each day all the pavilions are removed.

For each of the following m days, after another road is flipped, Naruto and Jiraiya choose a simple path — that is, a route which starts in a village and ends in a (possibly, the same) village, and doesn't contain any road twice. Since Naruto and Jiraiya also love ramen very much, they buy a single cup of ramen on each stone road and one of them eats it. Since they don't want to offend each other, they only choose routes where they can eat equal number of ramen cups. Since they both like traveling, they choose any longest possible path. After every renovation find the maximal possible length of a path (that is, the number of roads in it) they can follow.

Input

The first line contains the only positive integer n (2 ≤ n ≤ 500 000) standing for the number of villages in the Land of Fire.

Each of the following (n-1) lines contains a description of another road, represented as three positive integers u, v and t (1 ≤ u, v ≤ n, t ∈ \{0,1\}). The first two numbers denote the villages connected by the road, and the third denotes the initial type of the road: 0 for the sand one and 1 for the stone one. Roads are numbered from 1 to (n-1) in the order from the input.

The following line contains a positive integer m (1 ≤ m ≤ 500 000) standing for the number of days Naruto and Jiraiya travel for.

Each of the following m lines contains the single integer id (1 ≤ id ≤ n-1) standing for the index of the road whose type is flipped on the morning of corresponding day.

It is guaranteed that there is a road path between any pair of villages.

Output

Output m lines. In the i-th of them print the only integer denoting the maximal possible length of any valid path on the i-th day.

Example

Input


5
1 2 0
1 3 0
3 5 0
3 4 0
5
3
4
1
3
4


Output


3
2
3
3
2

Note

After the renovation of the 3-rd road the longest path consists of the roads 1, 2 and 4.

After the renovation of the 4-th road one of the longest paths consists of the roads 1 and 2.

After the renovation of the 1-st road one of the longest paths consists of the roads 1, 2 and 3.

After the renovation of the 3-rd road the longest path consists of the roads 1, 2 and 4.

After the renovation of the 4-rd road one of the longest paths consists of the roads 2 and 4.
10
5 7 0
2 10 1
1 5 0
6 8 0
4 9 1
2 5 1
10 8 0
2 3 1
4 2 1
10
9
9
9
5
2
5
7
2
3
2
 5
2 4 0
5 2 0
1 3 1
1 2 1
5
3
3
4
1
1
 20
9 11 0
1 5 0
1 14 0
5 17 0
14 3 0
16 6 0
9 2 0
6 4 0
11 10 0
12 7 0
8 18 0
13 1 0
18 11 0
8 6 0
5 10 0
5 15 0
2 20 0
19 17 0
7 17 0
20
9
11
11
14
14
5
5
10
10
4
4
18
17
18
17
17
8
8
15
17
 2
2 1 1
10
1
1
1
1
1
1
1
1
1
1

5
5
5
5
5
4
5
4
5
5
 2
3
2
3
2
 7
9
7
9
7
9
7
9
7
9
7
8
8
8
7
8
9
8
9
9
 1
0
1
0
1
0
1
0
1
0

#include <bits/stdc++.h>

using ll                            = long long;
using uint                          = unsigned int;
using ull                           = unsigned long long;
using ld                            = long double;
template<typename T> using max_heap = std::priority_queue<T>;
template<typename T> using min_heap = std::priority_queue<T, std::vector<T>, std::greater<T>>;
constexpr int popcount(const ull v) { return v ? __builtin_popcountll(v) : 0; }
constexpr int log2p1(const ull v) { return v ? 64 - __builtin_clzll(v) : 0; }
constexpr int lsbp1(const ull v) { return __builtin_ffsll(v); }
constexpr int clog(const ull v) { return v ? log2p1(v - 1) : 0; }
constexpr ull ceil2(const ull v) { return 1ULL << clog(v); }
constexpr ull floor2(const ull v) { return v ? (1ULL << (log2p1(v) - 1)) : 0ULL; }
constexpr bool btest(const ull mask, const int ind) { return (mask >> ind) & 1ULL; }
template<typename T> void bset(T& mask, const int ind) { mask |= ((T)1 << ind); }
template<typename T> void breset(T& mask, const int ind) { mask &= ~((T)1 << ind); }
template<typename T> void bflip(T& mask, const int ind) { mask ^= ((T)1 << ind); }
template<typename T> void bset(T& mask, const int ind, const bool b) { (b ? bset(mask, ind) : breset(mask, ind)); }
template<typename T, typename F, typename Merge, typename Compose, typename Apply>
class lazyseg
{
public:
    lazyseg(const std::vector<T>& vs,
            const Merge merge_,
            const T& e_,
            const Compose compose_,
            const F& id_,
            const Apply apply_) : m_size{(int)vs.size()}, m_depth{clog(m_size)}, m_half{1 << m_depth}, m_vals(m_half << 1, e_), m_ops(m_half << 1, id_), m_merge{merge_}, m_e{e_}, m_compose{compose_}, m_id{id_}, m_apply{apply_}
    {
        std::copy(vs.begin(), vs.end(), m_vals.begin() + m_half);
        for (int i = m_half - 1; i >= 1; i--) { up(i); }
    }
    T get(const int a) { return assert(a < m_size), fold(a, a + 1); }
    void set(int a, const T& v)
    {
        assert(0 <= a and a < m_size);
        top_down(a += m_half), top_down(a + 1), m_ops[a] = m_id, m_vals[a] = v;
        while (a >>= 1) { up(a); }
    }
    T fold(int l, int r)
    {
        assert(0 <= l and l <= r and r <= m_size);
        if (l >= r) { return m_e; }
        top_down(l += m_half), top_down(r += m_half);
        T accl = m_e, accr = m_e;
        for (; l < r; l >>= 1, r >>= 1) {
            if (l & 1) { accl = m_merge(accl, m_vals[l++]); }
            if (r & 1) { accr = m_merge(m_vals[--r], accr); }
        }
        return m_merge(accl, accr);
    }
    void act(int l, int r, const F& f)
    {
        assert(0 <= l and l <= r and r <= m_size);
        const int lin = l + m_half, rin = r + m_half;
        top_down(l += m_half), top_down(r += m_half);
        for (int ls = 1, rs = 1; l < r; l >>= 1, r >>= 1, ls <<= 1, rs <<= 1) {
            if (l & 1) { update(l++, f, ls); }
            if (r & 1) { update(--r, f, rs); }
        }
        bottom_up(lin), bottom_up(rin);
    }
    friend std::ostream& operator<<(std::ostream& os, const lazyseg& lseg)
    {
        auto lseg2 = lseg;
        os << "[";
        for (int i = 0; i < lseg.m_size; i++) { os << lseg2.get(i) << (i + 1 == lseg2.m_size ? "" : ","); }
        return (os << "]\n");
    }

private:
    void up(const int i) { m_vals[i] = m_merge(m_vals[i << 1], m_vals[i << 1 | 1]); }
    void update(const int a, const F& f, const int l) { m_ops[a] = m_compose(f, m_ops[a]), m_vals[a] = m_apply(f, m_vals[a], l); }
    void down(const int a, const int l) { update(a << 1, m_ops[a], l >> 1), update(a << 1 | 1, m_ops[a], l >> 1), m_ops[a] = m_id; }
    void top_down(const int a)
    {
        const int b = (a / (a & -a)) >> 1;
        for (int i = 0, l = m_half; i < m_depth; i++, l >>= 1) {
            const int v = a >> (m_depth - i);
            if (v > b) { break; }
            down(v, l);
        }
    }
    void bottom_up(int a)
    {
        a = (a / (a & -a)) >> 1;
        for (; a >= 1; a >>= 1) { up(a); }
    }
    const int m_size, m_depth, m_half;
    std::vector<T> m_vals;
    std::vector<F> m_ops;
    const Merge m_merge;
    const T m_e;
    const Compose m_compose;
    const F m_id;
    const Apply m_apply;
};


template<typename T = int>
struct edge
{
    using cost_type = T;
    int v;
    T c;
    edge(const int v_) : v{v_}, c{1} {}
    edge(const int v_, const T& c_) : v{v_}, c{c_} {}
    operator int() const { return v; }
    int to() const { return v; }
    T cost() const { return c; }
    friend std::ostream& operator<<(std::ostream& os, const edge& e) { return os << e.v << ":" << e.c; }
};
template<typename Edge>
class base_graph
{
public:
    base_graph(const int n) : sz{n}, es(n), res(n)
    {}
    void add_edge(const int u, const int v, const bool bi = false)
    {
        es[u].emplace_back(v);
        res[v].emplace_back(u);
        if (bi) {
            es[v].emplace_back(u);
            res[u].emplace_back(v);
        }
    }
    template<typename Cost>
    void add_edge(const int u, const int v, const Cost& c, const bool bi = false)
    {
        es[u].emplace_back(v, c);
        res[v].emplace_back(u, c);
        if (bi) {
            es[v].emplace_back(u, c);
            res[u].emplace_back(v, c);
        }
    }
    std::vector<Edge>& operator[](const int u) { return es[u]; }
    const std::vector<Edge>& operator[](const int u) const { return es[u]; }
    std::vector<Edge>& from(const int u) { return es[u]; }
    const std::vector<Edge>& from(const int u) const { return es[u]; }
    std::vector<Edge>& to(const int v) { return res[v]; }
    const std::vector<Edge>& to(const int v) const { return res[v]; }
    int size() const { return sz; }
    friend std::ostream& operator<<(std::ostream& os, const base_graph& g)
    {
        for (int i = 0; i < g.sz; i++) {
            for (const auto& e : g.es[i]) { os << i << "->" << e << '\n'; }
        }
        return os;
    }

private:
    int sz;
    std::vector<std::vector<Edge>> es, res;
};
using graph = base_graph<edge<>>;
template<typename Cost>
using cost_graph = base_graph<edge<Cost>>;
template<typename Edge = edge<>>
class hl_decomp
{
public:
    hl_decomp(base_graph<Edge>& g, const int r = 0) : pars(g.size(), -1), tops{pars}, ins{pars}, rins{pars}, outs{pars}
    {
        const int n = g.size();
        std::vector<int> sz(n, 1);
        auto dfs1 = [&](auto&& self, const int s, const int p) -> int {
            pars[s]  = p;
            int maxi = -1, max = 0;
            for (int i = 0; i < (int)g[s].size(); i++) {
                const auto& e = g[s][i];
                const int to  = e.to();
                if (p == to) { continue; }
                sz[s] += self(self, to, s);
                if (max < sz[g[s][i].to()]) { max = sz[g[s][i].to()], maxi = i; }
            }
            if (maxi != -1) { std::swap(g[s][maxi], g[s][0]); }
            return sz[s];
        };
        dfs1(dfs1, r, -1);
        tops[r]   = r;
        auto dfs2 = [&](auto&& self, const int s, const int p, int& ind) -> void {
            ins[s] = ind++, rins[ins[s]] = s;
            for (const auto& e : g[s]) {
                const int to = e.to();
                if (to == p) { continue; }
                tops[to] = (to == g[s][0].to() ? tops[s] : to);
                self(self, to, s, ind);
            }
            outs[s] = ind;
        };
        int ind = 0;
        dfs2(dfs2, r, -1, ind);
    }
    int pos(const int v) const { return ins[v]; }
    int at(const int n) const { return rins[n]; }
    std::pair<int, int> sub(const int v) const { return {ins[v], outs[v]}; }
    std::vector<std::pair<int, int>> path(int u, int v) const
    {
        using P = std::pair<int, int>;
        std::vector<P> head, tail;
        for (int pu = tops[u], pv = tops[v]; pu != pv;) {
            if (ins[pu] < ins[pv]) {
                tail.push_back({ins[pv], ins[v]});
                v = pars[pv], pv = tops[v];
            } else {
                head.push_back({ins[u], ins[pu]});
                u = pars[pu], pu = tops[u];
            }
        }
        head.push_back({ins[u], ins[v]});
        std::reverse(tail.begin(), tail.end());
        for (const auto& p : tail) { head.push_back(p); }
        return head;
    }
    friend std::ostream& operator<<(std::ostream& os, const hl_decomp& hld)
    {
        os << "rins = {";
        for (const int v : hld.rins) { os << v << ","; }
        os << "}\ntops = {";
        for (const int v : hld.tops) { os << v << ","; }
        return os << "}";
    }

private:
    std::vector<int> pars, tops, ins, rins, outs;
};
template<typename T> bool chmin(T& a, const T& b) { return (a > b ? a = b, true : false); }
template<typename T> bool chmax(T& a, const T& b) { return (a < b ? a = b, true : false); }
template<typename T> constexpr T inf_v      = std::numeric_limits<T>::max() / 4;
template<typename Real> constexpr Real pi_v = Real{3.141592653589793238462643383279502884};
template<typename T> constexpr T TEN(const int n) { return n == 0 ? T{1} : TEN<T>(n - 1) * T{10}; }
template<typename F> struct fix : F
{
    fix(F&& f) : F{std::forward<F>(f)} {}
    template<typename... Args> auto operator()(Args&&... args) const { return F::operator()(*this, std::forward<Args>(args)...); }
};
template<typename T, int n, int i = 0>
auto nd_array(int const (&szs)[n], const T x = T{}) { if constexpr (i == n) { return x; } else { return std::vector(szs[i], nd_array<T, n, i + 1>(szs, x)); } }
class printer
{
public:
    printer(std::ostream& os_ = std::cout) : m_os{os_} { m_os << std::fixed << std::setprecision(15); }
    template<typename... Args> int ln(const Args&... args) { return dump(args...), m_os << '\n', 0; }
    template<typename... Args> int el(const Args&... args) { return dump(args...), m_os << std::endl, 0; }
    template<typename... Args> int fmt(const std::string& s, const Args&... args) { return rec(s, 0, args...); }
private:
    template<typename T> int dump(const T& v) { return m_os << v, 0; }
    template<typename T> int dump(const std::vector<T>& vs) { for (int i = 0; i < (int)vs.size(); i++) { m_os << (i ? " " : ""), dump(vs[i]); } return 0; }
    template<typename T> int dump(const std::vector<std::vector<T>>& vss) { for (int i = 0; i < (int)vss.size(); i++) { m_os << (0 <= i or i + 1 < (int)vss.size() ? "\n" : ""), dump(vss[i]); } return 0; }
    template<typename T, typename... Args> int dump(const T& v, const Args&... args) { return dump(v), m_os << ' ', dump(args...), 0; }
    int rec(const std::string& s, int index) { return m_os << s.substr(index, s.size()), 0; }
    template<typename T, typename... Args> int rec(const std::string& s, int index, const T& v, const Args&... args) { return index == s.size() ? 0 : s[index] == '%' ? (tdump(v), rec(s, index + 1, args...)) : (m_os << s[index], rec(s, index + 1, v, args...)); }
    std::ostream& m_os;
};
printer out;
class scanner
{
public:
    scanner(std::istream& is_ = std::cin) : m_is{is_} { m_is.tie(nullptr), std::ios::sync_with_stdio(false); }
    template<typename T> T val() { T v; return m_is >> v, v; }
    template<typename T> T val(const T offset) { return val<T>() - offset; }
    template<typename T> std::vector<T> vec(const int n) { return make_v<T>(n, [this]() { return val<T>(); }); }
    template<typename T> std::vector<T> vec(const int n, const T offset) { return make_v<T>(n, [this, offset]() { return val<T>(offset); }); }
  template<typename T> std::vector<std::vector<T>> vvec(const int n0, const int n1) { return make_v<std::vector<T>>(n0, [this, n1]() { return vec<T>(n1); }); }
  template<typename T> std::vector<std::vector<T>> vvec(const int n0, const int n1, const T offset) { return make_v<std::vector<T>>(n0, [this, n1, offset]() { return vec<T>(n1, offset); }); }
    template<typename... Args> auto tup() { return std::tuple<std::decay_t<Args>...>{val<Args>()...}; }
    template<typename... Args> auto tup(const Args&... offsets) { return std::tuple<std::decay_t<Args>...>{val<Args>(offsets)...}; }
private:
    template<typename T, typename F>
    std::vector<T> make_v(const int n, F f)
    {
        std::vector<T> ans;
        for (int i = 0; i < n; i++) { ans.push_back(f()); }
        return ans;
    }
    std::istream& m_is;
};
scanner in;
#    define SHOW(...) static_cast<void>(0)
int main()
{
    const auto N = in.val<int>();
    std::vector<int> us(N - 1), vs(N - 1);
    std::vector<int> ts(N - 1);
    graph g(N);
    for (int i = 0; i < N - 1; i++) {
        std::tie(us[i], vs[i], ts[i]) = in.tup<int, int, int>(1, 1, 0);
        g.add_edge(us[i], vs[i], true);
    }
    std::vector<int> ds1(N, 0), ds2(N, 0);
    auto dfs1 = fix([&](auto dfs, const int s, const int p) -> void {
        for (const int to : g[s]) {
            if (to == p) { continue; }
            ds1[to] = ds1[s] + 1;
            dfs(to, s);
        }
    });
    dfs1(0, -1);
    const int s1 = std::max_element(ds1.begin(), ds1.end()) - ds1.begin();
    std::fill(ds1.begin(), ds1.end(), 0);
    dfs1(s1, -1);
    const int s2 = std::max_element(ds1.begin(), ds1.end()) - ds1.begin();
    auto dfs2    = fix([&](auto dfs, const int s, const int p) -> void {
        for (const int to : g[s]) {
            if (to == p) { continue; }
            ds2[to] = ds2[s] + 1;
            dfs(to, s);
        }
    });
    dfs2(s2, -1);
    SHOW(s1, s2);
    SHOW(ds1);
    SHOW(ds2);

    cost_graph<int> g1(N), g2(N);
    for (int i = 0; i < N - 1; i++) {
        const int u = us[i], v = vs[i];
        const int t = ts[i];
        if (ds1[u] < ds1[v]) {
            g1.add_edge(u, v, t);
        } else {
            g1.add_edge(v, u, t);
        }
        if (ds2[u] < ds2[v]) {
            g2.add_edge(u, v, t);
        } else {
            g2.add_edge(v, u, t);
        }
    }
    SHOW(g1);
    SHOW(g2);
    std::vector<int> ins1(N), outs1(N);
    std::vector<int> ins2(N), outs2(N);
    std::vector<int> vs1, vs2;
    std::vector<int> ps1(N, 0), ps2(N, 0);
    fix([&](auto dfs, const int s) -> void {
        ins1[s] = vs1.size();
        vs1.push_back(s);
        for (const auto [to, c] : g1[s]) {
            ps1[to] = ps1[s] ^ c;
            dfs(to);
        }
        outs1[s] = vs1.size() + 1;
    })(s1);
    fix([&](auto dfs, const int s) -> void {
        ins2[s] = vs2.size();
        vs2.push_back(s);
        for (const auto [to, c] : g2[s]) {
            ps2[to] = ps2[s] ^ c;
            dfs(to);
        }
        outs2[s] = vs2.size() + 1;
    })(s2);
    SHOW(ins1);
    SHOW(outs1);
    SHOW(ins2);
    SHOW(outs2);
    using pii = std::pair<int, int>;
    std::vector<pii> vals1, vals2;
    for (const int v1 : vs1) {
        if (ps1[v1]) {
            vals1.push_back({-inf_v<int>, ds1[v1]});
        } else {
            vals1.push_back({ds1[v1], -inf_v<int>});
        }
    }
    for (const int v2 : vs2) {
        if (ps2[v2]) {
            vals2.push_back({-inf_v<int>, ds2[v2]});
        } else {
            vals2.push_back({ds2[v2], -inf_v<int>});
        }
    }

    lazyseg seg1(
        vals1,
        [&](const pii& p1, const pii& p2) { return pii{std::max(p1.first, p2.first), std::max(p1.second, p2.second)}; },
        pii{-inf_v<int>, -inf_v<int>},
        [&](const bool f1, const bool f2) { return f1 ^ f2; },
        false,
        [&](const bool f, const pii& p, const int) {
            if (f) {
                return pii{p.second, p.first};
            } else {
                return p;
            }
        });
    lazyseg seg2(
        vals2,
        [&](const pii& p1, const pii& p2) { return pii{std::max(p1.first, p2.first), std::max(p1.second, p2.second)}; },
        pii{-inf_v<int>, -inf_v<int>},
        [&](const bool f1, const bool f2) { return f1 ^ f2; },
        false,
        [&](const bool f, const pii& p, const int) {
            if (f) {
                return pii{p.second, p.first};
            } else {
                return p;
            }
        });
    const auto M = in.val<int>();
    for (int i = 0; i < M; i++) {
        const int ei = in.val<int>(1);
        const int u = us[ei], v = vs[ei];
        const int w1 = (ds1[u] < ds1[v] ? v : u);
        const int w2 = (ds2[u] < ds2[v] ? v : u);
        const int l1 = ins1[w1], r1 = ins1[w1];
        seg1.act(l1, r1, true);
        const int l2 = ins2[w2], r2 = ins2[w2];
        seg2.act(l2, r2, true);
        int ans = -inf_v<int>;
        chmax(ans, seg1.fold(0, N).first);
        chmax(ans, seg2.fold(0, N).first);
        out.ln(ans);
    }
    return 0;
}

		  					  		    	   	 	   	 	