题目描述
很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治着整个星系。
某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球。这些星球通过特殊的以太隧道互相直接或间接地连接。
但好景不长,很快帝国又重新造出了他的超级武器。凭借这超级武器的力量,帝国开始有计划地摧毁反抗军占领的星球。由于星球的不断被摧毁,两个星球之间的通讯通道也开始不可靠起来。
现在,反抗军首领交给你一个任务:给出原来两个星球之间的以太隧道连通情况以及帝国打击的星球顺序,以尽量快的速度求出每一次打击之后反抗军占据的星球的连通块的个数。(如果两个星球可以通过现存的以太通道直接或间接地连通,则这两个星球在同一个连通块中)。
输入输出格式
输入格式:

输入文件第一行包含两个整数,
NN
N (
1<=N<=2M1 < = N < = 2M
1<=N<=2M) 和
MM
M (
1<=M<=200,0001 < = M < = 200,000
1<=M<=200,000),分别表示星球的数目和以太隧道的数目。星球用
00
0 ~
N−1N-1
N−1 的整数编号。
接下来的
MM
M 行,每行包括两个整数
XX
X,
YY
Y,其中(
0<=X<>Y0 < = X <> Y
0<=X<>Y 表示星球
xx
x 和星球
yy
y 之间有 “以太” 隧道,可以直接通讯。
接下来的一行为一个整数
kk
k ,表示将遭受攻击的星球的数目。
接下来的
kk
k 行,每行有一个整数,按照顺序列出了帝国军的攻击目标。这
kk
k 个数互不相同,且都在
00
0 到
n−1n-1
n−1 的范围内。

输出格式:

第一行是开始时星球的连通块个数。接下来的
KK
K 行,每行一个整数,表示经过该次打击后现存星球的连通块个数。

输入输出样例
输入样例#1: 复制
8 13
0 1
1 6
6 5
5 0
0 6
1 2
2 3
3 4
4 5
7 1
7 2
7 6
3 6
5
1
6
3
5
7
输出样例#1: 复制
1
1
1
2
3
3


并查集反着操作即可;

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
#include<cctype>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 600005
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 20100403
#define sq(x) (x)*(x)
#define eps 1e-15
const int N = 2500005;

inline int rd() {
    int x = 0;
    char c = getchar();
    bool f = false;
    while (!isdigit(c)) {
        if (c == '-') f = true;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f ? -x : x;
}

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}

int f[maxn];
int head[maxn];
bool fg[maxn];
int atk[maxn];
int cnt = 0;
int ans[maxn];

struct node {
    int from, to, nxt;
}edge[maxn];

void addedge(int u, int v) {
    edge[cnt].from = u; edge[cnt].to = v;
    edge[cnt].nxt = head[u]; head[u] = cnt++;
}

int findfa(int x) {
    if (x == f[x])return x;
    return f[x] = findfa(f[x]);
}


int main()
{
    //ios::sync_with_stdio(false);
    int n, m, k;
    cin >> n >> m;
    for (int i = 0; i <= n; i++) {
        head[i] = -1; f[i] = i;
    }
    for (int i = 0; i < m; i++) {
        int u, v; scanf("%d%d", &u, &v);
        addedge(u, v); addedge(v, u);
    }
    int  tot = 0;
    cin >> k;
    for (int i = 1; i <= k; i++) {
        int x; scanf("%d", &x);
        fg[x] = true; atk[i] = x;
    }
    tot = n - k;
    for (int i = 0; i < 2 * m; i++) {
        if (fg[edge[i].from] == false && fg[edge[i].to] == false) {
            if (findfa(edge[i].from) != findfa(edge[i].to)) {
                tot--;
                f[findfa(edge[i].from)] = f[findfa(edge[i].to)];
            }
        }
    }
    ans[k + 1] = tot;
    for (int i = k; i >= 1; i--) {
        int u = atk[i];
        tot++;
        fg[u] = false;
        for (int i = head[u]; i != -1; i = edge[i].nxt) {
            if (fg[edge[i].to] == false && findfa(edge[i].to) != findfa(u)) {
                tot--;
                f[findfa(edge[i].to)] = f[findfa(u)];
            }
        }
        ans[i] = tot;
    }
    for (int i = 1; i <= k + 1; i++)cout << ans[i] << endl;
    return 0;
}






#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<set>
#include<vector>
#include<queue>
#include<bitset>
#include<ctime>
#include<deque>
#include<stack>
#include<functional>
#include<sstream>
#include<cctype>
//#pragma GCC optimize("O3")
using namespace std;
#define maxn 600005
#define inf 0x3f3f3f3f
#define INF 0x7fffffff
typedef long long  ll;
typedef unsigned long long ull;
typedef unsigned int U;
#define ms(x) memset((x),0,sizeof(x))
const long long int mod = 1e9 + 7;
#define Mod 20100403
#define sq(x) (x)*(x)
#define eps 1e-15
const int N = 2500005;

inline int rd() {
    int x = 0;
    char c = getchar();
    bool f = false;
    while (!isdigit(c)) {
        if (c == '-') f = true;
        c = getchar();
    }
    while (isdigit(c)) {
        x = (x << 1) + (x << 3) + (c ^ 48);
        c = getchar();
    }
    return f ? -x : x;
}

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}

int f[maxn];
int head[maxn];
bool fg[maxn];
int atk[maxn];
int cnt = 0;
int ans[maxn];

struct node {
    int from, to, nxt;
}edge[maxn];

void addedge(int u, int v) {
    edge[cnt].from = u; edge[cnt].to = v;
    edge[cnt].nxt = head[u]; head[u] = cnt++;
}

int findfa(int x) {
    if (x == f[x])return x;
    return f[x] = findfa(f[x]);
}


int main()
{
    //ios::sync_with_stdio(false);
    int n, m, k;
    cin >> n >> m;
    for (int i = 0; i <= n; i++) {
        head[i] = -1; f[i] = i;
    }
    for (int i = 0; i < m; i++) {
        int u, v; scanf("%d%d", &u, &v);
        addedge(u, v); addedge(v, u);
    }
    int  tot = 0;
    cin >> k;
    for (int i = 1; i <= k; i++) {
        int x; scanf("%d", &x);
        fg[x] = true; atk[i] = x;
    }
    tot = n - k;
    for (int i = 0; i < 2 * m; i++) {
        if (fg[edge[i].from] == false && fg[edge[i].to] == false) {
            if (findfa(edge[i].from) != findfa(edge[i].to)) {
                tot--;
                f[findfa(edge[i].from)] = f[findfa(edge[i].to)];
            }
        }
    }
    ans[k + 1] = tot;
    for (int i = k; i >= 1; i--) {
        int u = atk[i];
        tot++;
        fg[u] = false;
        for (int i = head[u]; i != -1; i = edge[i].nxt) {
            if (fg[edge[i].to] == false && findfa(edge[i].to) != findfa(u)) {
                tot--;
                f[findfa(edge[i].to)] = f[findfa(u)];
            }
        }
        ans[i] = tot;
    }
    for (int i = 1; i <= k + 1; i++)cout << ans[i] << endl;
    return 0;
}