#include using namespace std; using ll = long long; class UnionFind { private: vector _parents; vector _size; int _vertexCount; public: UnionFind(int n) { _vertexCount = n; _parents.resize(n); _size.resize(n); for (int i = 0; i < n; i++) { _size[i] = 1; _parents[i] = i; } } int Root(int x) { if (_parents[x] == x) return x; return _parents[x] = Root(_parents[x]); } int Size(int x) { return _size[Root(x)]; } void Unite(int x, int y) { int rootX = Root(x); int rootY = Root(y); if (rootX == rootY) return; int from = rootX; int to = rootY; if (_size[from] > _size[to]) { swap(from, to); } _size[to] += _size[from]; _parents[from] = to; } vector Find(int x) { int root = Root(x); vector set; for (int i = 0; i < _vertexCount; i++) { if (Root(i) == root) { set.push_back(i); } } return set; } unordered_map> FindAll() { unordered_map> sets; for (int i = 0; i < _vertexCount; i++) { int root = Root(i); if (sets.find(root) != sets.end()) { sets[root].push_back(i); } else { sets.emplace(root, vector()); sets[root].push_back(i); } } return sets; } bool Same(int x, int y) { int rootX = Root(x); int rootY = Root(y); return rootX == rootY; } void Clear() { for (int i = 0; i < _vertexCount; i++) { _parents[i] = i; _size[i] = 1; } } int VertexCount() { return _vertexCount; } }; int main() { cin.tie(nullptr); ios::sync_with_stdio(false); int N, M; cin >> N >> M; assert(2 <= N && N <= 200000); assert(1 <= M && M <= 200000); vector> edges; vector> g(N, vector()); for (int i = 0; i < M; i++) { int u, v; cin >> u >> v; assert(1 <= u && u <= N); assert(1 <= v && v <= N); assert(u != v); u--; v--; if (u > v) { swap(u, v); } edges.emplace_back(u, v); g[u].push_back(v); g[v].push_back(u); } for (int i = 0; i < N; i++) { sort(g[i].begin(), g[i].end()); } int Q; cin >> Q; assert(1 <= Q && Q <= 200000); vector A(Q); set setA; for (int i = 0; i < Q; i++) { cin >> A[i]; assert(1 <= A[i] && A[i] <= M); A[i]--; setA.insert(A[i]); } assert(setA.size() == Q); ll cur = 0; queue q; vector sizes; vector seen(N); for (int i = 0; i < N; i++) { if(seen[i]) continue; int s = 0; q.push(i); while (!q.empty()) { int n = q.front(); q.pop(); if (seen[n]) continue; seen[n] = true; s++; for (int p : g[n]) { q.push(p); } } sizes.push_back(s); } { ll left = sizes[0]; for (int i = 1; i < sizes.size(); i++) { cur += left * sizes[i]; left += sizes[i]; } } for (int i = 0; i < Q; i++) { int u = edges[A[i]].first; int v = edges[A[i]].second; { int t = lower_bound(g[u].begin(), g[u].end(), v) - g[u].begin(); swap(g[u][t], g[u][g[u].size() - 1]); g[u].pop_back(); } { int t = lower_bound(g[v].begin(), g[v].end(), u) - g[v].begin(); swap(g[v][t], g[v][g[v].size() - 1]); g[v].pop_back(); } ll a = 0, b = 0; bool invalid = false; bool f = seen[u]; q.push(u); while (!q.empty()) { int n = q.front(); q.pop(); if (seen[n] == !f) continue; if (n == v) invalid = true; seen[n] = !f; a++; for (int p : g[n]) { q.push(p); } } f = seen[v]; q.push(v); while (!q.empty()) { int n = q.front(); q.pop(); if (seen[n] == !f) continue; seen[n] = !f; b++; for (int p : g[n]) { q.push(p); } } if (!invalid) cur += a * b; cout << cur << endl; } }