#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
struct Edge { int u, v, d, id; };
struct Query { int type, x, y, id; };
struct RollbackDSU {
vector<int> parent, sz;
vector<pair<int, int>> history;
RollbackDSU(int n) {
parent.resize(n + 1);
sz.resize(n + 1, 1);
for (int i = 1; i <= n; i++) parent[i] = i;
}
int find(int i) {
while (parent[i] != i) i = parent[i];
return i;
}
bool merge(int u, int v) {
int root_u = find(u), root_v = find(v);
if (root_u == root_v) return false;
if (sz[root_u] < sz[root_v]) swap(root_u, root_v);
history.push_back({root_v, root_u});
parent[root_v] = root_u;
sz[root_u] += sz[root_v];
return true;
}
void rollback(int target_size) {
while (history.size() > target_size) {
int v = history.back().first, u = history.back().second;
history.pop_back();
parent[v] = v;
sz[u] -= sz[v];
}
}
};
int main() {
ios::sync_with_stdio(false); cin.tie(0);
int n, m; cin >> n >> m;
vector<Edge> edges(m + 1);
for (int i = 1; i <= m; i++) {
cin >> edges[i].u >> edges[i].v >> edges[i].d;
edges[i].id = i;
}
int q; cin >> q;
vector<Query> queries(q);
for (int i = 0; i < q; i++) {
cin >> queries[i].type >> queries[i].x >> queries[i].y;
queries[i].id = i;
}
int S = sqrt(q);
vector<int> ans(q, -1), current_d(m + 1), edge_status(m + 1, 0);
for (int i = 1; i <= m; i++) current_d[i] = edges[i].d;
for (int l = 0; l < q; l += S) {
int r = min(q - 1, l + S - 1);
vector<Query> ask;
vector<int> changed_edges, upd_idx;
for (int i = l; i <= r; i++) {
if (queries[i].type == 1) {
edge_status[queries[i].x] = 1;
upd_idx.push_back(i);
} else ask.push_back(queries[i]);
}
for (int i = 1; i <= m; i++)
if (edge_status[i]) changed_edges.push_back(i);
vector<Edge> fixed;
for (int i = 1; i <= m; i++)
if (!edge_status[i]) fixed.push_back({edges[i].u, edges[i].v, current_d[i], i});
sort(fixed.begin(), fixed.end(), [](const Edge& a, const Edge& b) { return a.d > b.d; });
sort(ask.begin(), ask.end(), [](const Query& a, const Query& b) { return a.y > b.y; });
RollbackDSU dsu(n);
int ptr = 0;
for (auto& qry : ask) {
while (ptr < fixed.size() && fixed[ptr].d >= qry.y) {
dsu.merge(fixed[ptr].u, fixed[ptr].v);
ptr++;
}
int snapshot = dsu.history.size();
for (int i = l; i <= r; i++) {
if (queries[i].type == 1 && queries[i].id < qry.id) {
edges[queries[i].x].d = queries[i].y;
}
}
for (int id : changed_edges) {
if (edges[id].d >= qry.y) dsu.merge(edges[id].u, edges[id].v);
}
ans[qry.id] = dsu.sz[dsu.find(qry.x)];
dsu.rollback(snapshot);
for (int i = l; i <= r; i++) {
if (queries[i].type == 1) edges[queries[i].x].d = current_d[queries[i].x];
}
}
for (int i = l; i <= r; i++) {
if (queries[i].type == 1) current_d[queries[i].x] = queries[i].y;
edge_status[queries[i].x] = 0;
}
for (int id : changed_edges) edges[id].d = current_d[id];
}
for (int i = 0; i < q; i++) if (ans[i] != -1) cout << ans[i] << "\n";
return 0;
}