#include #include #include #include #include using std::vector; using std::pair; typedef long long LL; const int MAXN = 100001; const int P = 1000000007; int n, m; int dfs_id; int root = 1; int depth[MAXN], point_id[MAXN]; int go[MAXN][18]; vector edges[MAXN]; pair subtree[MAXN]; struct SegmentTreeNode { int l, r, mid; int max_val, max_mul; int label; } tree[270000]; void DFS(int p, int d, int father) { subtree[p].first = ++dfs_id; depth[p] = d; point_id[dfs_id] = p; go[p][0] = father; for (int child : edges[p]) { if (child == father) continue; DFS(child, d + 1, p); } subtree[p].second = dfs_id; } void BuildSegmentTree(int p, int l, int r) { SegmentTreeNode &node = tree[p]; node.l = l; node.r = r; node.mid = (l + r) >> 1; node.max_val = 0; node.max_mul = 0; node.label = 0; if (l == r) { node.max_mul = point_id[l]; } else { BuildSegmentTree(p << 1, l, node.mid); BuildSegmentTree(p << 1 | 1, node.mid + 1, r); node.max_mul = (LL)tree[p << 1].max_mul * tree[p << 1 | 1].max_mul % P; } } void Init() { assert(scanf("%d%d", &n, &m) == 2); for (int i = 1; i < n; ++i) { int u, v; assert(scanf("%d%d", &u, &v) == 2); edges[u].push_back(v); edges[v].push_back(u); } root = rand() % n + 1; dfs_id = 0; DFS(root, 0, 0); for (int j = 1; j < 18; ++j) for (int i = 1; i <= n; ++i) { go[i][j] = go[go[i][j - 1]][j - 1]; } BuildSegmentTree(1, 1, n); } int GoUp(int u, int d) { for (int i = 0; d; ++i, d >>= 1) if (d & 1) u = go[u][i]; return u; } int LCA(int u, int v) { u = GoUp(u, depth[u] - depth[v]); if (u == v) return u; for (int j = 17; j >= 0; --j) { if (go[u][j] != go[v][j]) { u = go[u][j]; v = go[v][j]; } } assert(u != v && go[u][0] == go[v][0]); return go[u][0]; } void AddSegment(int p, int l, int r, int val) { SegmentTreeNode &node = tree[p]; if (l <= node.l && r >= node.r) { node.label += val; return; } if (node.label) { node.max_val += node.label; tree[p << 1].label += node.label; tree[p << 1 | 1].label += node.label; node.label = 0; } if (l <= node.mid) AddSegment(p << 1, l, r, val); if (r > node.mid) AddSegment(p << 1 | 1, l, r, val); int l_max_val = tree[p << 1].max_val + tree[p << 1].label; int r_max_val = tree[p << 1 | 1].max_val + tree[p << 1 | 1].label; node.max_val = l_max_val; node.max_mul = tree[p << 1].max_mul; if (r_max_val > node.max_val) { node.max_val = r_max_val; node.max_mul = 1; } if (r_max_val == node.max_val) node.max_mul = (LL)node.max_mul * tree[p << 1 | 1].max_mul % P; } int GetMaxVal() { return tree[1].max_val + tree[1].label; } void Work() { int sum = 0; while (m--) { char op; int x, y; assert(scanf(" %c%d%d", &op, &x, &y) == 3); if (depth[x] < depth[y]) std::swap(x, y); int val; if (op == '+') { ++sum; val = 1; } else { --sum; val = -1; } int lca = LCA(x, y); if (lca == y) { int w = GoUp(x, depth[x] - depth[y] - 1); AddSegment(1, subtree[root].first, subtree[root].second, val); AddSegment(1, subtree[w].first, subtree[w].second, -val); AddSegment(1, subtree[x].first, subtree[x].second, val); } else { AddSegment(1, subtree[x].first, subtree[x].second, val); AddSegment(1, subtree[y].first, subtree[y].second, val); } if (GetMaxVal() == sum) { printf("%d\n", tree[1].max_mul); } else { puts("-1"); } } } int main() { Init(); Work(); return 0; }