#pragma GCC optimize("O3") #include using namespace std; #define rep(i, a, n) for (int i = a; i < (int)(n); i++) using ll = long long; template struct UnionFind { vector parent, rank, siz; UnionFind(T n) : parent(n, -1), rank(n, 0), siz(n, 1) {} T root(T x) { if (parent[x] == -1) { return x; } else { return parent[x] = root(parent[x]); } } bool same(T x, T y) { return root(x) == root(y); } bool merge(T x, T y) { T root_x = root(x), root_y = root(y); if (root_x == root_y) { return false; } if (rank[root_x] < rank[root_y]) { swap(root_x, root_y); } parent[root_y] = root_x; if (rank[root_x] == rank[root_y]) { rank[root_x]++; } siz[root_x] += siz[root_y]; return true; } T size(int x) { return siz[root(x)]; } }; int main() { ll n, m; cin >> n >> m; UnionFind uf(n); vector u(m), v(m); rep(i, 0, m) { cin >> u[i] >> v[i]; u[i]--; v[i]--; } set destructed; int q; cin >> q; vector jyunban(q); rep(i, 0, q) { cin >> jyunban[i]; jyunban[i]--; destructed.insert(jyunban[i]); } ll ans = n * (n - 1) / 2; rep(i, 0, m) { if (!destructed.count(i)) { ll usize = uf.size(u[i]), vsize = uf.size(v[i]); if (!uf.same(u[i], v[i])) { ans -= usize * vsize; uf.merge(u[i], v[i]); } } } vector answers(q); for (int i = q - 1; i >= 0; --i) { answers[i] = ans; int idx = jyunban[i]; int a = u[idx], b = v[idx]; if (!uf.same(a, b)) { ans -= (ll)uf.size(a) * uf.size(b); uf.merge(a, b); } } rep(i, 0, q) { cout << answers[i] << endl; } }